bzoj3173:[Tjoi2013]最长上升子序列

Description

给定一个序列,初始为空。现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置。每插入一个数字,我们都想知道此时最长上升子序列长度是多少?

Input

第一行一个整数N,表示我们要将1到N插入序列中,接下是N个数字,第k个数字Xk,表示我们将k插入到位置Xk(0<=Xk<=k-1,1<=k<=N)

Output

N行,第i行表示i插入Xi位置后序列的最长上升子序列的长度是多少。

Sample Input

3
0 0 2

Sample Output

1
1
2

HINT

100%的数据 n<=100000

题解

Treap+LIS

分析一下Treap的正确性:假设插入点p,再插入点q,由题意可知q>p,所以有两种情况,第一种,q插在p的前面,第二种,插在p的后面,由于插在p前面,q又大于p,所以q的存在不会影响p的LIS,如果插在p的后面,则Treap也会将其插在p的后面,所以同样不会影响结果,由此可知,可使用Treap来实现插入。

 

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #define inf 1<<29
  5 #define maxn 100010
  6 int cnt,tcnt,ans[maxn],n,v[maxn],root;
  7 using namespace std;
  8 struct treap{
  9     int pri,lc,rc,siz;
 10 }a[maxn];
 11 void pushup(int o){a[o].siz=a[a[o].lc].siz+a[a[o].rc].siz+1;}
 12 void lturn(int &o)
 13 {
 14     int t=a[o].rc;
 15     a[o].rc=a[t].lc;
 16     a[t].lc=o;
 17     a[t].siz=a[o].siz;
 18     pushup(o);
 19     o=t;
 20     return ;
 21 }
 22 void rturn(int &o)
 23 {
 24     int t=a[o].lc;
 25     a[o].lc=a[t].rc;
 26     a[t].rc=o;
 27     a[t].siz=a[o].siz;
 28     pushup(o);
 29     o=t;
 30     return ;
 31 }
 32 void insert(int &o,int rank)
 33 {
 34     if(!o)
 35     {
 36         o=++cnt;
 37         a[o]=(treap){rand(),0,0,1};
 38         return ;
 39     }
 40     a[o].siz++;
 41     if(rank<=a[a[o].lc].siz)
 42     {
 43         insert(a[o].lc,rank);
 44         if(a[a[o].lc].pri>a[o].pri)rturn(o);
 45     }
 46     else 
 47     {
 48         insert(a[o].rc,rank-a[a[o].lc].siz-1);
 49         if(a[a[o].rc].pri>a[o].pri)lturn(o);
 50     }
 51     return ;
 52 }
 53 void dfs(int o)
 54 {
 55     if(!o)return ;
 56     dfs(a[o].lc);
 57     v[++tcnt]=o;
 58     dfs(a[o].rc);
 59     return ;
 60 }
 61 void solve()
 62 {
 63     int f[maxn],len=0;
 64     for(int i=1 ; i<=n ; ++i )
 65     {
 66         int l=1,r=len;
 67         if(v[i]>f[len])
 68         {
 69             f[++len]=v[i];
 70             ans[v[i]]=len;
 71             continue;
 72         }
 73         while(r>l)
 74         {
 75             int m=(r+l)>>1;
 76             if(v[i]>f[m])l=m+1;
 77             else r=m;
 78         }
 79         f[l]=v[i];
 80         ans[v[i]]=l;
 81     }
 82     return ;
 83 }
 84 int main()
 85 {
 86     scanf("%d",&n);
 87     srand(n);
 88     for(int i=1 ; i<=n ; ++i)
 89     {
 90         int b;
 91         scanf("%d",&b);
 92         insert(root,b);
 93     }
 94     dfs(root);
 95     solve();
 96     for(int i=1 ; i<=n ; ++i)
 97     {
 98         ans[i]=max(ans[i],ans[i-1]);
 99         printf("%d\n",ans[i]);
100     }
101     return 0;
102 }

 

 

 

posted @ 2017-09-19 10:59  傅judge  阅读(206)  评论(0编辑  收藏  举报