其實說鴿就鴿,也是一種不鴿!
這是一種常用(對,就是常用,但是我才會的東西)的資料結構,主要用於插入刪除,檢視第k大,區間翻轉.......操作(我目前就會幾個簡單的,後續會更新其他操作)
這篇很詳細
我也不知道解釋啥!我也挺迷的,反正就在保證結構特性的情況下隨便轉轉就完事了,我能想通這樣寫為什麼對,就是想不來如何創新
多看看上旋方式,如何避免鏈式最壞情況(有句話說的好對,沒事就splay下),就能看懂為什麼splay函式這麼寫了
後續會有區間翻轉,虛實鏈剖分==內容更新
#includeusing namespace std;
const double pi = acos(-1.0);
typedef long long ll;
const ll mod =998244353;
const int n=1e5+7;
int sz;///當前節點個數
int rt;///根節點編號
int fa[n];///下標父親節點編號
int key[n];///編號i對應值
int size[n];///編號i子樹大小
int num[n];///編號i重複次數
int son[n][2];///編號i左右兒子 左0右1
void clear(int x)///清除乙個節點資訊
int get(int x)///確定乙個節點是父親的左兒子還是右兒子
void update(int x)///更新乙個節點size
}void link(int x,int y,int z)///x連在y下面關係為z
void rotate(int x)///旋轉,與自己的父親交換位置
void splay(int x)///講乙個節點上旋至根節點
rt=x;
}void insert(int x)///插入節點,新節點上旋至根節點保證整體的平衡
int now=rt,ffa=0;
while(1)
ffa=now;
now=son[now][x>key[now]];
if(!now)
}}int find(int x)
if(!son[rt][0]&&!son[rt][1])///只有乙個節點
if(!son[rt][0])///只有乙個兒子的情況
if(!son[rt][1])
///左右兒子都健在的情況,吧pre上旋至根,要刪的節點會變成只有右兒子的情況,這就好搞了啊
int tmp=rt;
int left=pre();
splay(left);
link(son[tmp][1],rt,1);
clear(tmp);
update(rt);
}int main()
{ ios::sync_with_stdio(false);
int q;
cin>>q;
while(q--)
{ int choose,x;
cin>>choose>>x;
if(choose==1) insert(x);
if(choose==2) del(x);
if(choose==3) {cout《第二個例題文藝平衡樹,就是splay的區間翻轉,(當然還可以用分塊莽過去,分塊多好告,真的是,用splay幹嘛~!)
我們先建一顆權值splay,如果要翻轉乙個區間,只需要吧l-1翻到root,r+1翻到root的右兒子,r+1的左子樹就是要翻轉的區間
加上乙個tag標記就完事了(和線段樹的lazy乙個吊樣),之後在找下乙個l-1和r+1執行操作,找的時候肯定是從root開始找的,如果當前節點有tap,就pushdown下去,交換左右兒子,tag標記順移下去就完事了,最後終須遍歷一下就完事了
第三個例題 排序機械臂
區間反轉而已,只是需要一點思維(我木得腦子,我看的題解改的)先排序,原陣列裡面的值就沒用了,只用維護排序後的相對順序就好了,二叉樹建權值splay,維護下標,然後按順序把節點翻到rt,左子樹個數就是第幾位(因為後面有區間修改,所以有兩個哨兵)然後就是區間翻轉的板子了(魔改了半天,還改的效率愈發低下了)
總結 伸展樹Splay
感覺我在聯賽還差4天的時候學習splay有點慌,但還是要學一下。我們先對splay的陣列進行一些定義 struct nodet n 2 我們的splay應該要支援以下幾個操作 如下 includeusing namespace std const int n 500010 int root,tot ...
伸展樹splay學習小記
splay是基本操作,rotate是splay的基本操作。splay now,root 把now splay到root的下面。單旋和雙旋就不說了。我們可以簡化操作,如果是一字型 方向相同 則先旋father,否則先旋now。然後再旋now。rotate now是指將now繞father rotate...
資料結構 Splay伸展樹 普通平衡樹
題目描述 您需要寫一種資料結構 可參考題目標題 來維護一些數,其中需要提供以下操作 插入x數 刪除x數 若有多個相同的數,因只刪除乙個 查詢x數的排名 若有多個相同的數,因輸出最小的排名 查詢排名為x的數 求x的前驅 前驅定義為小於x,且最大的數 求x的後繼 後繼定義為大於x,且最小的數 輸入 第一...