bzoj3173

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

 
 
因为后面插入的数一定比前面的大, 所以更后插入的对当前的答案没有任何影响,所以预处理出每个数的最终位置,然后动态规划即可。
时间复杂度O(nlogn)
 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string>
 4 #include<string.h>
 5 #include<iostream>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<math.h>
 9 #include<vector>
10 #include<map>
11 #include<set>
12 #define il inline
13 #define re register
14 using namespace std;
15 const int N=1000001;
16 int l[N],r[N],rnd[N],siz[N],v[N],s[N],cnt,now,root,n,ans[N],g;
17 il void update(re int k){
18     siz[k]=siz[l[k]]+siz[r[k]]+1;
19 }
20 il void rturn(re int &k){
21     int t=l[k];l[k]=r[t];r[t]=k;update(k);update(t);k=t;
22 }
23 il void lturn(re int &k){
24     int t=r[k];r[k]=l[t];l[t]=k;update(k);update(t);k=t;
25 }
26 il void insert(re int &k,re int rank){
27     if(!k){
28         k=(++cnt);rnd[k]=rand();siz[k]=1;return;
29     }
30     siz[k]++;
31     if(siz[l[k]]<rank){
32         insert(r[k],rank-siz[l[k]]-1);
33         if(rnd[r[k]]<rnd[k]) lturn(k);
34     }
35     else{
36         insert(l[k],rank);
37         if(rnd[l[k]]<rnd[k]) rturn(k);
38     }
39 }
40 il int read(){
41     re int hs=0;re char c=getchar();
42     while(!isdigit(c)) c=getchar();
43     while(isdigit(c)){
44         hs=(hs<<3)+(hs<<1)+c-'0';
45         c=getchar();
46     }
47     return hs;
48 }
49 il void dfs(re int k){
50     if(!k) return;
51     dfs(l[k]);
52     v[++now]=k;
53     dfs(r[k]);
54 }
55 int main(){
56     memset(s,127,sizeof(s));s[0]=-1000000000;n=read();
57     for(re int i=1,x;i<=n;i++){
58         x=read();insert(root,x);
59     }
60     dfs(root);
61     for(re int i=1,t;i<=n;i++){
62         t=upper_bound(s,s+g+1,v[i])-s;
63         if(s[t-1]<=v[i]){
64             s[t]=min(s[t],v[i]);
65             ans[v[i]]=t;
66             g=max(g,t);
67         }
68     }
69     for(re int i=1;i<=n;i++){
70         ans[i]=max(ans[i-1],ans[i]);
71         printf("%d\n",ans[i]);
72     }
73     return 0;
74 }

 

posted @ 2016-08-24 11:33  ExiledPoet  阅读(338)  评论(0编辑  收藏  举报