[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
题解:
splay,按位置维护,先加入的点小,后加的大
每次加入直接模拟splay的插入。
由于没有延迟标记,所以不需要pushdown,但要pushup
每次pushup要维护两个值,当前节点结尾的最长上升子序列,当前子树的最长子序列
推测可知,当前节点结尾的最长上升子序列只由左节点子树的序列的递推而来,因为左子树位置在前面,且小
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int MAXN=500010; 7 int tot2,tot1,s[MAXN],pre[MAXN],ch[MAXN][2],key[MAXN]; 8 int size[MAXN],root,n,m,maxn[MAXN],g[MAXN]; 9 void NewNode(int &x,int fa,int k) 10 { 11 if (tot2) x=s[tot2--]; 12 else x=++tot1; 13 key[x]=k; 14 size[x]=1; 15 pre[x]=fa; 16 ch[x][0]=ch[x][1]=0; 17 } 18 void pushup(int x) 19 { 20 int lson=ch[x][0],rson=ch[x][1]; 21 size[x]=size[lson]+size[rson]+1; 22 maxn[x]=max(max(g[x],maxn[rson]),maxn[lson]); 23 if (key[x]==2e9||key[x]==0) maxn[x]=0,g[x]=0; 24 } 25 void rotate(int x,bool t) 26 { 27 int y=pre[x]; 28 ch[y][!t]=ch[x][t]; 29 pre[ch[x][t]]=y; 30 if (pre[y]) 31 ch[pre[y]][ch[pre[y]][1]==y]=x; 32 pre[x]=pre[y]; 33 ch[x][t]=y; 34 pre[y]=x; 35 pushup(y);pushup(x); 36 } 37 int getkth(int r,int k) 38 { 39 int x=size[ch[r][0]]+1; 40 if (k==x) return r; 41 if (k<x) getkth(ch[r][0],k); 42 else getkth(ch[r][1],k-x); 43 } 44 void splay(int x,int goal) 45 { 46 while (pre[x]!=goal) 47 { 48 if (pre[pre[x]]==goal) 49 { 50 rotate(x,ch[pre[x]][0]==x); 51 } 52 else 53 { 54 int y=pre[x],kind=ch[pre[y]][0]==y; 55 if (ch[y][kind]==x) 56 { 57 rotate(x,!kind); 58 rotate(x,kind); 59 } 60 else 61 { 62 rotate(y,kind); 63 rotate(x,kind); 64 } 65 } 66 } 67 pushup(x); 68 if (goal==0) root=x; 69 } 70 int main() 71 {int i,x; 72 cin>>n; 73 NewNode(root,0,2e9); 74 NewNode(ch[root][1],root,0); 75 for (i=1; i<=n; i++) 76 { 77 scanf("%d",&x); 78 splay(getkth(root,x+1),0); 79 splay(getkth(root,x+2),root); 80 NewNode(ch[ch[root][1]][0],ch[root][1],i); 81 splay(ch[ch[root][1]][0],0); 82 g[root]=maxn[ch[root][0]]+1; 83 pushup(root); 84 printf("%d\n",maxn[root]); 85 } 86 }