BZOJ3173:[TJOI2013]最长上升子序列(Splay)
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
Solution
设$f[i]$表示以$i$数字为结尾的最长上升子序列长度。
可以发现插入一个数的时候只有当前这个数的$f$会变化,也就是当前这个数前面一段的$max(f)+1$。
用$Splay$维护一下就好了。
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #define N (100009) 5 using namespace std; 6 7 int n,m,p,ans,Root; 8 int Father[N],Son[N][2],f[N],Max[N],Size[N]; 9 10 inline int read() 11 { 12 int x=0,w=1; char c=getchar(); 13 while (c<'0' || c>'9') {if (c=='-') w=-1; c=getchar();} 14 while (c>='0' && c<='9') x=x*10+c-'0', c=getchar(); 15 return x*w; 16 } 17 18 int Get(int x) 19 { 20 return Son[Father[x]][1]==x; 21 } 22 23 void Pushup(int x) 24 { 25 Max[x]=f[x]; 26 if (Son[x][0]) Max[x]=max(Max[x],Max[Son[x][0]]); 27 if (Son[x][1]) Max[x]=max(Max[x],Max[Son[x][1]]); 28 Size[x]=Size[Son[x][0]]+Size[Son[x][1]]+1; 29 } 30 31 void Rotate(int x) 32 { 33 int wh=Get(x); 34 int fa=Father[x],fafa=Father[fa]; 35 if (fafa) Son[fafa][Son[fafa][1]==fa]=x; 36 Father[fa]=x; Son[fa][wh]=Son[x][wh^1]; 37 if (Son[fa][wh]) Father[Son[fa][wh]]=fa; 38 Father[x]=fafa; Son[x][wh^1]=fa; 39 Pushup(fa); Pushup(x); 40 } 41 42 void Splay(int x,int tar) 43 { 44 for (int fa; (fa=Father[x])!=tar; Rotate(x)) 45 if (Father[fa]!=tar) Rotate(Get(fa)==Get(x)?fa:x); 46 if (!tar) Root=x; 47 } 48 49 int Next(int now) 50 { 51 if (!Son[now][1]) return now; 52 now=Son[now][1]; 53 while (Son[now][0]) now=Son[now][0]; 54 return now; 55 } 56 57 int Findkth(int x) 58 { 59 int now=Root; 60 while (1) 61 if (x<=Size[Son[now][0]]) now=Son[now][0]; 62 else 63 { 64 x-=Size[Son[now][0]]; 65 if (x==1) {Splay(now,0); return now;} 66 x--; now=Son[now][1]; 67 } 68 } 69 70 int main() 71 { 72 n=read(); 73 Max[1]=Max[n+2]=f[1]=f[n+2]=-2e9; 74 Father[n+2]=1; Son[1][1]=n+2; 75 for (int i=2; i<=n+2; ++i) Size[i]=1; 76 Size[1]=2; Root=1; 77 for (int i=2; i<=n+1; ++i) 78 { 79 p=read(); p=Findkth(p+1); 80 int nxt=Next(Root); 81 82 Splay(1,0); 83 if (nxt!=1) Splay(nxt,1); 84 f[i]=Max[Son[nxt][0]]+1; 85 ans=max(ans,f[i]); 86 printf("%d\n",ans); 87 88 Splay(p,0); 89 if (nxt!=p) Splay(nxt,p); 90 Father[i]=nxt; Son[nxt][0]=i; 91 Max[i]=f[i]; 92 Splay(i,0); 93 } 94 }