码迷,mamicode.com
首页 > 编程语言 > 详细

Codeforces 486E LIS of Sequence --树状数组

时间:2015-01-16 22:12:22      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:

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

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

 

Codeforces 486E LIS of Sequence --树状数组

标签:

原文地址:http://www.cnblogs.com/whatbeg/p/4229737.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!