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维护一下队列的信息,然后直接做就好。膜拜KuribohG
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <algorithm> 5 using namespace std; 6 const int MAXN=1000001; 7 struct Treap 8 { 9 int ch[2],dat,key,size,tms; 10 }treap[MAXN]; 11 int tot,root,cnt,a[MAXN],dp[MAXN],c[MAXN],ans[MAXN],n; 12 inline int cmp(int x,int tar) 13 { 14 if(treap[x].dat==tar) return -1; 15 return (treap[x].dat<tar?0:1); 16 } 17 inline void maintain(int x) 18 { 19 treap[x].size=treap[treap[x].ch[0]].size+treap[treap[x].ch[1]].size+1; 20 } 21 inline int rotate(int &x,int d) 22 { 23 int p=treap[x].ch[d^1]; 24 treap[x].ch[d^1]=treap[p].ch[d]; 25 treap[p].ch[d]=x; 26 maintain(x); 27 maintain(p); 28 x=p; 29 } 30 void ins(int &x,int m,int tar) 31 { 32 if(!x) 33 { 34 tot++; 35 treap[tot].key=rand(); treap[tot].size=1; treap[tot].tms=1; treap[tot].dat=tar; x=tot; 36 return; 37 } 38 int d; 39 if(m<=treap[treap[x].ch[0]].size) ins(treap[x].ch[0],m,tar),d=0; 40 else ins(treap[x].ch[1],m-treap[treap[x].ch[0]].size-1,tar),d=1; 41 if(treap[treap[x].ch[d]].key>treap[x].key) rotate(x,d^1); 42 maintain(x); 43 } 44 void work(int x) 45 { 46 if(treap[x].ch[0]) work(treap[x].ch[0]); 47 a[++n]=treap[x].dat; 48 if(treap[x].ch[1]) work(treap[x].ch[1]); 49 } 50 int main(int argc, char *argv[]) 51 { 52 int i,x; 53 scanf("%d",&n); 54 for(i=1,x;i<=n;i++) { 55 scanf("%d",&x); 56 ins(root,x,i); 57 } 58 n=0; 59 work(root); 60 for(i=1;i<=n;i++) 61 c[i]=n+1; 62 for(i=1;i<=n;i++) 63 { 64 int sub=lower_bound(c,c+n+1,a[i])-c; 65 dp[i]=sub; 66 c[dp[i]]=min(c[dp[i]],a[i]); 67 ans[a[i]]=dp[i]; 68 } 69 for(i=1;i<=n;i++) ans[i]=max(ans[i],ans[i-1]); 70 for(i=1;i<=n;i++) printf("%d ",ans[i]); 71 return 0; 72 }