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
0 0 2
Sample Output
1
1
2
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 }