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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

P3391-[模板]文艺平衡树【Splay】

發布時間:2023/12/3 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P3391-[模板]文艺平衡树【Splay】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題

題目連接:https://www.luogu.org/problemnew/show/P3391


題目大意

一個序列,m個操作翻轉[l..r][l..r][l..r]區間。求最終序列


解題思路

節點維護編號,然后答案就是中序遍歷。然后翻轉的話我們先考慮一個性質。

若這是初始狀態(l-1和r+1反了)
然后將l-1旋到根節點,將r+1選到根的右節點,

然后l~rl\sim rlr就是一個單獨的子樹,可以自己翻轉。
但這里不翻轉先,因為最終只有一次詢問,所以我們可以用延遲標記。


codecodecode

#include<cstdio> #include<algorithm> #define INF 2100000000 #define N 100010 using namespace std; struct splay{int v[N],father[N],root;int l[N],r[N];int sum[N],mark[N];int n,points;void Updata(int x){sum[x]=sum[l[x]]+sum[r[x]]+1;}void Downdata(int x){if(mark[x]){mark[l[x]]^=1;mark[r[x]]^=1;mark[x]=0;swap(l[x],r[x]);}}void New(int x,int vs,int fa){l[x]=r[x]=0;sum[x]=1;v[x]=vs;father[x]=fa;}void Rotate(int x){int y=father[x];int z=father[y];int k=r[y]==x;if(r[z]==y) r[z]=x;else l[z]=x;father[x]=z;if(k) r[y]=l[x];else l[y]=r[x];father[k?l[x]:r[x]]=y;if(k) l[x]=y;else r[x]=y;father[y]=x;Updata(y);Updata(x);}void Splay(int at,int to){while(father[at]!=to){int y=father[at];int z=father[y];if(z!=to)(r[z]==y)^(r[z]==at)?Rotate(at):Rotate(y);Rotate(at);}if(to==0)root=at;}void Insert(int x){int now=root,ff=0;while(now)ff=now,now=(x>v[now]?r[now]:l[now]);now=++n;if(ff&&x>v[now]) r[ff]=now;else if(ff) l[ff]=now;New(now,x,ff);Splay(now,0);}int GetValByRank(int k){int now=root;while(1){Downdata(now);if(sum[l[now]]>=k) now=l[now];else if(sum[l[now]]+1==k) return now;else k-=sum[l[now]]+1,now=r[now];}}void Work(int ls,int rs){ls=GetValByRank(ls);rs=GetValByRank(rs+2);Splay(ls,0);Splay(rs,ls);mark[l[r[root]]]^=1;}void Write(int x,int mn){Downdata(x);if(l[x]) Write(l[x],mn);if(v[x]>1&&v[x]<mn+2) printf("%d ",v[x]-1);if(r[x]) Write(r[x],mn);} }a; int main(){//freopen("testdata.in","r",stdin);//freopen("data.out","w",stdout);int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n+2;i++)a.Insert(i);while(m--){int l,r;scanf("%d%d",&l,&r);a.Work(l,r);}a.Write(a.root,n); }

總結

以上是生活随笔為你收集整理的P3391-[模板]文艺平衡树【Splay】的全部內容,希望文章能夠幫你解決所遇到的問題。

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