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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

洛谷P3391文艺平衡树(Splay)

發(fā)布時間:2025/6/17 编程问答 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 洛谷P3391文艺平衡树(Splay) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

  題目傳送門

  轉(zhuǎn)載自https://www.cnblogs.com/yousiki/p/6147455.html,轉(zhuǎn)載請注明出處

  

經(jīng)典引文

空間效率:O(n) 時間效率:O(log n)插入、查找、刪除 創(chuàng)造者:Daniel Sleator 和 Robert Tarjan
優(yōu)點:每次查詢會調(diào)整樹的結(jié)構(gòu),使被查詢頻率高的條目更靠近樹根。

Tree Rotation


? 樹的旋轉(zhuǎn)是splay的基礎(chǔ),對于二叉查找樹來說,樹的旋轉(zhuǎn)不破壞查找樹的結(jié)構(gòu)。 ?

Splaying

? Splaying是Splay Tree中的基本操作,為了讓被查詢的條目更接近樹根,Splay Tree使用了樹的旋轉(zhuǎn)操作,同時保證二叉排序樹的性質(zhì)不變。 Splaying的操作受以下三種因素影響:
  • 節(jié)點x是父節(jié)點p的左孩子還是右孩子
  • 節(jié)點p是不是根節(jié)點,如果不是
  • 節(jié)點p是父節(jié)點g的左孩子還是右孩子
同時有三種基本操作: ?

Zig Step


當(dāng)p為根節(jié)點時,進(jìn)行zip step操作。 當(dāng)x是p的左孩子時,對x右旋; 當(dāng)x是p的右孩子時,對x左旋。 ?

Zig-Zig Step

當(dāng)p不是根節(jié)點,且x和p同為左孩子或右孩子時進(jìn)行Zig-Zig操作。 當(dāng)x和p同為左孩子時,依次將p和x右旋; 當(dāng)x和p同為右孩子時,依次將p和x左旋。 ? ?

Zig-Zag Step

當(dāng)p不是根節(jié)點,且x和p不同為左孩子或右孩子時,進(jìn)行Zig-Zag操作。 當(dāng)p為左孩子,x為右孩子時,將x左旋后再右旋。 當(dāng)p為右孩子,x為左孩子時,將x右旋后再左旋。 ? ?

應(yīng)用

? Splay Tree可以方便的解決一些區(qū)間問題,根據(jù)不同形狀二叉樹中序遍歷結(jié)果不變的特性,可以將區(qū)間按順序建二叉查找樹。 每次自下而上的一套splay都可以將x移動到根節(jié)點的位置,利用這個特性,可以方便的利用Lazy的思想進(jìn)行區(qū)間操作。 對于每個節(jié)點記錄size,代表子樹中節(jié)點的數(shù)目,這樣就可以很方便地查找區(qū)間中的第k小或第k大元素。 對于一段要處理的區(qū)間[x, y],首先splay x-1到root,再splay y+1到root的右孩子,這時root的右孩子的左孩子對應(yīng)子樹就是整個區(qū)間。 這樣,大部分區(qū)間問題都可以很方便的解決,操作同樣也適用于一個或多個條目的添加或刪除,和區(qū)間的移動。

?

最后附上自己寫的洛谷的模板題的代碼: 

?

#include<bits/stdc++.h> using namespace std; const int N=1e5+7; int n,m,root,tot; struct Node{int ch[2],size;int fa,mark,val;void add(int x,int y){ch[0]=ch[1]=mark=0;val=x;fa=y;size=1;} }t[N]; inline int read() {char ch=getchar();int num=0;bool flag=false;while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}return flag?-num:num; } inline void pushup(int x) {int l=t[x].ch[0],r=t[x].ch[1];t[x].size=t[l].size+t[r].size+1; } inline void pushdown(int x) {if(t[x].mark){t[t[x].ch[0]].mark^=1;t[t[x].ch[1]].mark^=1;swap(t[x].ch[0],t[x].ch[1]);t[x].mark=0;} } inline void rotate(int x) {int y=t[x].fa;int z=t[y].fa;int k=(t[y].ch[1]==x);t[z].ch[t[z].ch[1]==y]=x;t[x].fa=z;t[t[x].ch[k^1]].fa=y;t[y].ch[k]=t[x].ch[k^1];t[x].ch[k^1]=y;t[y].fa=x;pushup(y);pushup(x); } inline void splay(int x,int tag) {while(t[x].fa!=tag){int y=t[x].fa;int z=t[y].fa;if(z!=tag)(t[y].ch[1]==x)^(t[z].ch[1]==y)?rotate(x):rotate(y);rotate(x);}if(tag==0)root=x; } inline void insert(int x) {int now=root,fa=0;while(now)fa=now,now=t[now].ch[x>t[now].val];now=++tot;if(fa)t[fa].ch[x>t[fa].val]=now;t[now].add(x,fa);splay(now,0); } inline int find(int x) {int now=root;while(555){pushdown(now);if(t[t[now].ch[0]].size>=x)now=t[now].ch[0];else if(t[t[now].ch[0]].size+1==x)return now;else x-=(t[t[now].ch[0]].size+1),now=t[now].ch[1];} } inline void work(int l,int r) {l=find(l);r=find(r+2);splay(l,0);splay(r,l);t[t[t[root].ch[1]].ch[0]].mark^=1; } inline void print(int x) {pushdown(x);if(t[x].ch[0])print(t[x].ch[0]);if(t[x].val>1&&t[x].val<n+2)printf("%d ",t[x].val-1);if(t[x].ch[1])print(t[x].ch[1]); } int main() {n=read();m=read();for(int i=1;i<=n+2;i++)insert(i);for(int i=1;i<=m;i++){int l=read();int r=read();work(l,r);}print(root);return 0; }

?

?

?

?

?

轉(zhuǎn)載于:https://www.cnblogs.com/cytus/p/8252154.html

總結(jié)

以上是生活随笔為你收集整理的洛谷P3391文艺平衡树(Splay)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。