資料結構 Splay BZOJ1500維修數列

2021-08-14 06:06:55 字數 3175 閱讀 5337

做了一套簡單的練習後,用splay處理區間問題就變得非常容易了。

總的來說,所有的splay有關,涉及區間的問題,都會基於select操作(其實就是根據排名找點)

node * find_id(node *x,int k)
我寫的遞迴版本,比較容易理解,但最好改為迴圈實現。

然後,有了這一操作,我們可以將splay tree中的任意乙個區間「提取」出來

例如翻轉操作:

void rev(int k,int

len)

這樣的做法很顯然需要預設兩個哨兵節點,乙個在最前,乙個最後。

其實所有的區間操作,無非就是這樣乙個既定的套路,唯一有所不同的,也只有在pushup和pushdown中才能體現。

也正是因此,pushup和pushdown的操作具有很強的靈活性,分別概述過於複雜,我在這裡就簡單提及一下這兩個操作的注意事項:

pushup操作的目的,是將子節點的資訊重新反饋到當前節點。因此任何涉及更改子節點的資訊後,都必須使用pushup操作。是乙個上傳的過程。

pushdown則與之相反,是將當前節點的資訊(懶標記為主)下傳給子節點,必須遵守乙個原則:即與pushup操作不衝突。也就是說,任何時候,當你使用一次pushdown,再做一次pushup,是不能夠將pushdown操作所改變的資訊抹去的。這一點在本題很有體現:在區間賦值操作中,如果僅僅更新當前節點,是不能夠滿足要求的,因為當再做一次pushup操作時,子節點的懶標記並未處理,造成當前節點又被恢復原樣。

以上就是splay處理區間問題的方法,

對於節點維護哪些資訊,可以當做線段樹來考慮,因為同為二叉樹,線段樹和平衡樹有很多相同之處。

對於本題的做法,就再簡單提及一點:

本題必須使用釋放空間的方式來完成刪除,否則會t

成套路的方法,沒必要刷過多的題,做一兩道經典的就可以了。

#include

#include

#include

#include

#include

#define sf scanf

#define pf printf

#define maxn 500100

#define inf 0x3fffffff

using namespace std;

struct nodetree[maxn];

node *root,*nil=&tree[0],*ncnt=&tree[1];

bool flag=0;

stack

emt;

int a[maxn];

void

read(int &x)

x=c-'0';

while(c=getchar(),c!=eof&&c>='0'&&c<='9')

x=x*10+c-'0';

if(flag)

x=-x;

}node *newnode(int val)

void pushup(node *x)

void pushdownx(node *x)

if(x->flag!=inf)

}void pushdown(node *x)

if(x->flag!=inf)

if(x->ch[0]!=nil)

pushdownx(x->ch[0]);

if(x->ch[1]!=nil)

pushdownx(x->ch[1]);

}void

rotate(node *x)

void splay(node *x,node *rt)

else

}}node * find_id(node *x,int k)

node * findnext(node *x,int d)

return x;

}void build(int l,int r,node *fa,int d)

node * ins(int k,int val)

node *y=findnext(x->ch[1],0);

splay(y,x);

y->ch[0]=newnode(val);

y->ch[0]->fa=y;

pushup(y);

pushup(x);

return y->ch[0];

}void

fre(node *x)

void

del(int k,int len)

void

mak(int k,int len,int val)

void

rev(int k,int len)

void

get(int k,int len)

void

mas()

void print(node *x)]\n ",x-tree,x->key,x->maxs,x->ch[0]-tree,x->ch[1]-tree,x->fa-tree);

pf("%d ",x->key);

print(x->ch[1]);

}int n,m;

int k,len,val;

char s[20];

int main()

node *x1=x;

while(x!=nil)

splay(x1,nil);

}else

if(s[0]=='d')

else

if(s[0]=='r')

else

if(s[0]=='g')

else

if(s[2]=='k')

else

//print(root);

//pf("\n-----------------------------\n");}}

2017就是我們的喜悅,

我們的挫敗,

我們的成就,

我們的悔恨,

是我們封存的標本。

幸好,明天我們還會忘記新的事物,

所以我們不害怕時間,

時間會向前奔跑,

我們也會。

資料結構 1 5章

一 資料結構以及相關概念的定義 二 抽象資料型別 三 演算法的時間複雜度和空間複雜度 一 線性表的定義和基本操作 二 線性表的實現 1.順序儲存結構 define list init size 100 線性表儲存空間的初始分配量 define listincrement 10 線性表儲存空間的分配增...

15 資料結構和演算法應用

大問題拆分成規模小的問題,往往用到遞迴 八皇后深度優先搜尋法 不一定得到的是最優解,價效比方案 判斷貪心法,看每一步是不是最優解,而最終的結果不見得是最優解 0 1揹包問題,就是如下,乙個揹包裝東西只能裝一種 邏輯複雜,跟分治法類似 動態規劃法特點,查表,就是拆分問題,將問題記錄到表,然後查表 我們...

資料結構基礎 15 基數排序

基數排序是一種借助 多關鍵字排序 的思想來實現 單關鍵字排序 的內部排序演算法。實現多關鍵字排序通常有兩種作法 最低位優先法 lsd 先對k 0 進行排序,並按 k 0 的不同值將記錄序列分成若干子串行之後,分別對 k 1 進行排序,k d 1 依次類推,直至最後對最次位關鍵字排序完成為止。最高位優...