BZOJ3173:[TJOI2013]最长上升子序列(Splay)
生活随笔
收集整理的這篇文章主要介紹了
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
30 0 2
Sample Output
11
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 }?
轉載于:https://www.cnblogs.com/refun/p/10362312.html
總結
以上是生活随笔為你收集整理的BZOJ3173:[TJOI2013]最长上升子序列(Splay)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何在NEO共识节点间分配任务
- 下一篇: 前嗅ForeSpider中数据采集界面介