现在的位置: 首页 > 综合 > 正文

hdu 3564 Another Lis

2017年10月11日 ⁄ 综合 ⁄ 共 1706字 ⁄ 字号 评论关闭

Lis
(lis.cpp/in/out)


给你一个刚开始是空的序列,我们将数字1N依次加入到序列中,每次只将单个数字添加到指定的位置

我们想知道每次数字添加(注:指插入)之后,整个序列的LIS(最长上升子序列)的长度是多少

对于每个文件,第一行是一个数字N(1<= N <= 100000),接下来有N个数字,第k个数字xk表示我们将k加到第xk(0<=
xk <= k-1)
个位置上

对于每个样例,输出N行,第i行表示将i加入序列之后的答案

样例:

输入:

3

00 2

输出:

1

1

2

Hint
In the sample, we add three numbers to the sequence, and form three sequences. a. 1 b. 2 1 c. 2 1 3

如果是单纯的LIS的话,我们用NlogN的算法就能解决这一题

但是题目说还需要插入

但是如果我们知道了最终的位置,能做吗?当然很好做了,一次LIS即可!

所以,先把最终的位置给确定下来

我们来看,不管你前面怎么插入,最后一个的位置肯定就是输入的那个位置!

所以转换一下,把原本的找位置变成找空位(即输入为 a ,就找从左到右的第 a 个空位)

这样我们就可以吧最终每个数的位置给确定下来,然后再一次LIS不就完了!

比如看样例,0 0 2

我们首先确定最后 3 的位置为3(我们改为1基准,所以2+1=3)                 位置:1 2 3

然后确定2的位置,从左到右的第1(0+1=1)个空位,为1                           位置:1 2 3

再确定1的位置,从左到右第1(0+1=1)个空位,为2                                   位置:1 23

所以,最终1~3的位置为 2 1 3 

我们再对位置做一次LIS即可

现在问题就变成了怎么确定最终的位置,前面也说了,数空位,典型的线段树!!!

代码也就出来了

    /*http://blog.csdn.net/jiangzh7 
    By Jiangzh*/  
    #include<cstdio>  
    #include<cstring>  
    #define max(a,b) ((a)>(b)?(a):(b))  
    const int N=100000+10;  
    const int inf=0x3f3f3f3f;  
    int n,a[N],tmp[N],c[N],len;  
    int free[N*4];  
      
    void build_tree(int p,int l,int r)  
    {  
        if(l==r) {free[p]=1;return;}  
        int m=(l+r)>>1;  
        build_tree(p<<1,l,m);  
        build_tree((p<<1)+1,m+1,r);  
        free[p]=free[p<<1]+free[(p<<1)+1];  
    }  
      
    void insert(int p,int l,int r,int cnt,int x)  
    {  
        if(l==r) {free[p]--;a[x]=l;return;}  
        free[p]--;  
        int m=(l+r)>>1;  
        if(free[p<<1]>=cnt) insert(p<<1,l,m,cnt,x);  
        else insert((p<<1)+1,m+1,r,cnt-free[p<<1],x);  
        free[p]=free[p<<1]+free[(p<<1)+1];  
    }  
      
    int find(int a)  
    {  
        int l=1,r=len,mid;  
        while(l<=r)  
        {  
            mid=(l+r)>>1;  
            if(a>c[mid]) l=mid+1;  
            else r=mid-1;  
        }  
        return l;  
    }  
      
    int main()  
    {  
        freopen("lis.in","r",stdin);  
        freopen("lis.out","w",stdout);  
        scanf("%d",&n);  
        for(int i=1;i<=n;i++) scanf("%d",&tmp[i]);  
        build_tree(1,1,n);  
        for(int i=n;i>=1;i--) insert(1,1,n,tmp[i]+1,i);  
        for(int i=1;i<=n;i++)  
        {  
            int k=find(a[i]);  
            len=max(len,k);  
            c[k]=a[i];  
            printf("%d\n",len);  
        }  
        return 0;  
    }  

抱歉!评论已关闭.