無比強大的資料結構 伸展樹總結

來源:互聯網
上載者:User

連結 :http://www.notonlysuccess.com/index.php/splay-tree/

論文連結:http://www.docin.com/p-62465596.html

其實本來不想學splay樹的,因為好像平時做題不怎麼用到,但是,請注意,書到用時方恨少啊,多一點儲備,就多一分機會

論文裡說,動態樹也要用splay來維護的說,有的斜率最佳化的題也要用splay來最佳化,所以,這幾天我將我找到的splay的題目刷了下,整理如下

我覺得伸展樹的作用應該分為兩類,一類主要體現在維護區間的作用上,而另一類則是和普通的平衡樹一樣

首先介紹一下普通平衡樹都有的功能

普通平衡樹的功能主要有   

 插入 刪除 一個數

 找 前驅  後繼  第k大 小

求大於等於或小於等於某個數的個數(可以求逆序數)

確定一個數的排名

我找了一些基本的資料結構題 ,用 treap 和 splay 都實現了下,效率差不多

CSDN代碼沒有收縮功能,所以就不放這裡了

splay的普通平衡樹功能 :  模板在這裡

下面是splay最重要的功能,對區間各種性質的維護

notonlysuccess的部落格裡已經有了很詳細的介紹和一些習題,我就把做過的題貼上來吧

普通平衡樹功能,找第k大,插入刪除等    鬱悶的出納員   題解

找前驅 後繼 刪除一個節點,直接將要刪除的節點旋轉到根,然後刪除根節點即可       寵物收養所:  題解

營業額統計   題解

區間更新,求和,模板題

區間翻轉   題解

Queue-jumpers 

  要注意離散化的方法,其他動作對伸展樹來說就相當於類比     題解

區間切割插入     題解

上面的題都做了就可以挑戰下下面兩個重口味的題目了

poj 3580        這道題會用到伸展樹的各種操作,主要是交換兩個相鄰的區間,直接切割一個區間,然後再插入相應的位置即可  題解

維修數列       這題的最大子列和 和  區間翻轉結合起來 製造了一個巨大的坑,如果發現不了,下面這組資料可以告訴你為什麼,不過最好還是自己去發現,

6
20
259
-231 -919  241  -676 -978
MAKE-SAME
4 3 772
REVERSE
2 5
MAX-SUM

維修數列的題解在這裡

呵呵,伸展樹搞定了,可以開工其他以前可望不可即的資料結構了

伸展樹的模板

#include<cstdio>typedef __int64 lld;const int inf = ~0u>>2;#define L ch[x][0]#define R ch[x][1]#define KT (ch[ch[rt][1]][0])const int maxn = 222222;struct SplayTree{int ch[maxn][2];int pre[maxn],sz[maxn],val[maxn];int rt,top;void Rotate(int x,int f) {int y = pre[x];down(y);   down(x);ch[y][!f] = ch[x][f];pre[ ch[x][f] ] = y;pre[x] = pre[y];if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] = x;ch[x][f] = y;pre[y] = x;up(y);}void Splay(int x,int goal) {down(x);while(pre[ x ] != goal ) {down( pre[pre[x]] ); down( pre[x] ); down(x);if(pre[ pre[x] ] == goal) Rotate( x , ch[ pre[x] ][0] == x ); else  {int y = pre[x] ,z = pre[y];int f = ( ch[z][0] == y);if(ch[y][f] == x) Rotate( x , !f ),Rotate( x , f );else Rotate( y , f ),Rotate( x , f );}}up(x);if(goal == 0) rt = x;}void RTO(int k,int goal) {int x=rt;down(x);while(sz[ L ] + 1 != k) {if(k < sz[ L ] + 1)  x = L ;else {k -= (sz[ L ] + 1);x = R;}down(x);}Splay(x,goal);}void vist(int x){if(x){printf("結點%2d : 左兒子  %2d   右兒子  %2d  val: %2d sum=%I64d\n",x,ch[x][0],ch[x][1],val[x],sum[x]);vist(L);vist(R);}}void debug() {puts("");vist(rt);  puts("");}void up(int x) {sz[x] = 1 + sz[ L ] + sz[ R ];sum[x] = val[x] + sum[ L ] + sum[ R ];}void down(int x) {if(add[x]) {val[ L ] += add[ x ];val[ R ] += add[ x ];add[ L ] += add[ x ];add[ R ] += add[ x ];sum[ L ] += (lld)add[x] * sz[ L ];sum[ R ] += (lld)add[x] * sz[ R ];add[ x ] = 0;}}void Newnode(int &x,int c,int f) {x=++top;L = R  = 0;  sz[x]=1;pre[x]=f;val[x] = sum[x] = c;    add[x] = 0;}void build(int &x,int l,int r,int f) {if(l>r) return ;int m=l+r>>1;Newnode(x , num[m] , f);build( L , l , m-1 , x);build( R , m + 1, r , x);up(x);}void init(int n) {    ch[0][0]=ch[0][1]=pre[0]=0;sz[0]=rt=top=0;add[0]=sum[0]=0;Newnode(rt,-1,0);Newnode(ch[rt][1],-1,rt);sz[rt]=2;for(int i=1;i<=n;i++) scanf("%d",&num[i]);build(KT,1,n,ch[rt][1]);up(ch[rt][1]);  up(rt);}void update() {int l,r,c;scanf("%d%d%d",&l,&r,&c);RTO(l,0);RTO(r+2,rt);add[KT] += c;val[KT] += c;sum[KT] += (lld) c * sz[KT];}void query() {int l,r;scanf("%d%d",&l,&r);RTO(l,0);RTO(r+2,rt);printf("%I64d\n",sum[KT]);}lld sum[maxn];int add[maxn];int num[maxn];}spt;int main() {int m,n;char op[5];scanf("%d%d",&n,&m);spt.init(n);while(m--) {    scanf("%s",op);if(op[0]=='Q') spt.query();else spt.update();}return 0;}/*4 101 2 3 4Q 2 4*/

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.