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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

【bzoj 3173】[Tjoi2013]最长上升子序列

發布時間:2024/4/17 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【bzoj 3173】[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

Sample Output

1
1
2

HINT

100%的數據 n<=100000

?

易得,令f[i]表示以數字i結尾的最長上升子序列長度,則新加入一個數時不會影響到其他的f[i]。

在線寫法:用平衡樹直接模擬,每一次用位置的前綴f[i]的最大值+1來作為當前的新加入的數的f[i],然后將其插入到指定位置。輸出答案時直接查找當前所有f[i]的最大值。

離線寫法:求出最終序列然后nlogn求一次LIS即可,可以用樹狀數組或平衡樹實現。

?

【fhq-treap 在線】

1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdlib> 5 using namespace std; 6 const int N=1e5+5; 7 int n,root,cnt,rt1,rt2,pos,ch[N][6]; 8 #define lc ch][0 9 #define rc ch][1 10 #define rnd ch][2 11 #define sz ch][3 12 #define v ch][4 13 #define mx ch][5 14 int read() 15 { 16 int x=0,f=1;char c=getchar(); 17 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 18 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 19 return x*f; 20 } 21 void up(int w) 22 { 23 w[sz]=w[lc][sz]+w[rc][sz]+1; 24 w[mx]=max(w[lc][mx],w[rc][mx]); 25 w[mx]=max(w[mx],w[v]); 26 } 27 void split(int w,int& l,int& r,int k) 28 { 29 if(!w){l=r=0;return;} 30 int lson=w[lc][sz]; 31 if(k<=lson){r=w;split(w[lc],l,w[lc],k);} 32 else {l=w;split(w[rc],w[rc],r,k-lson-1);} 33 up(w); 34 } 35 int merge(int a,int b) 36 { 37 if(!a||!b)return a+b; 38 if(a[rnd]<b[rnd]){a[rc]=merge(a[rc],b);up(a);return a;} 39 else {b[lc]=merge(a,b[lc]);up(b);return b;} 40 } 41 void ins(int& w,int x,int k) 42 { 43 if(x[rnd]<w[rnd]||!w){split(w,x[lc],x[rc],k);w=x;up(w);return;} 44 int lson=w[lc][sz]; 45 if(k<=lson)ins(w[lc],x,k); 46 else ins(w[rc],x,k-lson-1); 47 up(w); 48 } 49 int query(int pos) 50 { 51 rt1=rt2=0;split(root,rt1,rt2,pos); 52 int ans=rt1[mx];root=merge(rt1,rt2); 53 return ans; 54 } 55 int main() 56 { 57 n=read(); 58 for(int i=1;i<=n;i++) 59 { 60 pos=read(); 61 cnt++;cnt[v]=query(pos)+1; 62 cnt[sz]=1;cnt[rnd]=rand(); 63 ins(root,cnt,pos); 64 printf("%d\n",root[mx]); 65 } 66 return 0; 67 } View Code

?

【樹狀數組 離線】

1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 const int N=1e5+5; 6 int n,id,cnt,f[N],ans[N],a[N],num[N],bit[N]; 7 int read() 8 { 9 int x=0,f=1;char c=getchar(); 10 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 11 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 12 return x*f; 13 } 14 int lowbit(int x){return x&(-x);} 15 void ins(int x){while(x<=n)bit[x]--,x+=lowbit(x);} 16 int pos(int x) 17 { 18 int now=0,ans=0; 19 for(int i=17;i>=0;i--) 20 { 21 now+=(1<<i); 22 if(now<n&&ans+bit[now]<x)ans+=bit[now]; 23 else now-=(1<<i); 24 } 25 return now+1; 26 } 27 int main() 28 { 29 n=read(); 30 for(int i=1;i<=n;i++) 31 { 32 a[i]=read();bit[i]++; 33 if(i+lowbit(i)<=n)bit[i+lowbit(i)]+=bit[i]; 34 } 35 for(int i=n;i>=1;i--) 36 id=pos(a[i]+1),num[id]=i,ins(id); 37 for(int i=1;i<=n;i++) 38 { 39 id=lower_bound(f+1,f+cnt+1,num[i])-f; 40 if(id>cnt)f[++cnt]=num[i]; 41 else f[id]=num[i]; 42 ans[num[i]]=id; 43 } 44 for(int i=1;i<=n;i++)ans[i]=max(ans[i],ans[i-1]),printf("%d\n",ans[i]); 45 return 0; 46 } View Code

?

轉載于:https://www.cnblogs.com/zsnuo/p/7918389.html

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的【bzoj 3173】[Tjoi2013]最长上升子序列的全部內容,希望文章能夠幫你解決所遇到的問題。

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