日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ3173:[TJOI2013]最长上升子序列(Splay)

發布時間:2025/7/14 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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

Sample Output

1
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 }

?

轉載于:https://www.cnblogs.com/refun/p/10362312.html

總結

以上是生活随笔為你收集整理的BZOJ3173:[TJOI2013]最长上升子序列(Splay)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。