zoukankan      html  css  js  c++  java
  • Codeforces 486E LIS of Sequence --树状数组求LIS

    题意: 一个序列可能有多个最长子序列,现在问每个元素是以下三个种类的哪一类:

    1.不属于任何一个最长子序列

    2.属于其中某些但不是全部最长子序列

    3.属于全部最长子序列

    解法: 我们先求出dp1[i]表示1~i 的最长递增子序列长度, dp2[i]表示 n~i 的最长递减子序列长度(严格增减),这里我们可以用维护最大值的树状数组来解决,开始还以为要用nlogn求LIS的那种算法,当然那样应该也可以,这里元素值是1~10^5的,可以直接用树状数组,如果元素值任意的话,我们离散化一下也可以用树状数组。

    求出dp1[],dp2[]后,我们先判断第1类: 当dp1[i] + dp2[i] != Length+1 (Length为LIS长度)的话,说明前后不一致,不属于最长子序列。

    再判第3类,如果某个元素属于其中的一些最长子序列,那么他的dp1值一定不是唯一的,还有别的dp1值也等于他的dp1值,如1 2 3 5,那么dp1[2] = dp1[3] = 2.

    所以先把第1类判掉以后,不考虑第1类,看dp1值是否重复来判第3类。第1,3类判完剩下的就是第2类了。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <string>
    #include <vector>
    #include <map>
    #define lll __int64
    using namespace std;
    #define N 100107
    
    int a[N],c[N],n,MAX;
    int dp1[N],dp2[N];
    string S;
    int lowbit(int x) { return x&-x; }
    void modify(int up,int x,int val) {
        if(up) {
            while(x <= MAX) {
                c[x] = max(c[x],val);
                x += lowbit(x);
            }
        }
        else {
            while(x > 0) {
                c[x] = max(c[x],val);
                x -= lowbit(x);
            }
        }
    }
    int getmax(int up,int x) {
        int maxi = 0;
        if(up) {
            while(x > 0) {
                maxi = max(maxi,c[x]);
                x -= lowbit(x);
            }
        }
        else {
            while(x <= MAX) {
                maxi = max(maxi,c[x]);
                x += lowbit(x);
            }
        }
        return maxi;
    }
    map<int,int> mp;
    
    int main()
    {
        int i,j;
        while(scanf("%d",&n)!=EOF)
        {
            S = "#"; MAX = 0;
            for(i=1;i<=n;i++) cin>>a[i], S += "0", MAX = max(MAX,a[i]);
            memset(c,0,sizeof(c));
            int LIS = 0;
            for(i=1;i<=n;i++) {
                int maxi = getmax(1,a[i]-1);
                dp1[i] = maxi+1;
                LIS = max(LIS,dp1[i]);
                modify(1,a[i],dp1[i]);
            }
            memset(c,0,sizeof(c));
            for(i=n;i>=1;i--) {
                int maxi = getmax(0,a[i]+1);
                dp2[i] = maxi+1;
                modify(0,a[i],dp2[i]);
            }
            mp.clear();
            for(i=1;i<=n;i++) {
                if(dp1[i] + dp2[i] - 1 != LIS) S[i] = '1';
                else mp[dp1[i]]++;
            }
            for(i=1;i<=n;i++)
                if(S[i] != '1' && mp[dp1[i]] == 1) S[i] = '3';
            for(i=1;i<=n;i++)
                if(S[i] == '0') S[i] = '2';
            cout<<S.substr(1,n)<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    User-agent大全
    获取https
    python 异常类型
    Git之生成ssh公钥
    Git 笔记
    iptables
    如何在CentOS 6.4上安装并使用OpenVZ?
    centos6.5 pptpd
    CentOS 6.x安装Metasploit
    CentOS 6.5下安装BeEF
  • 原文地址:https://www.cnblogs.com/whatbeg/p/4229737.html
Copyright © 2011-2022 走看看