NOI2005 維護數列 Splay

2022-05-07 08:24:09 字數 2298 閱讀 7489

題面

洛谷p2042

解析這道題集齊了大部分splay的經典操作,上課時wys老師講了一下,這個題還是很值得一做的

基操:splay上的所有區間操作都需要提取區間,如果要提取乙個[l, r]的區間,只需要把l-1的點轉到根,再把r+1的點轉到根的右兒子,那麼根的右兒子的左兒子的整顆子樹就是我們要提取的區間

操作1:插入

這個題的插入並非插入乙個數,而是插入乙個數列,乙個乙個的插入肯定會t的,所以就把插入的數列先建成一棵樹,再提取區間,這時根的右兒子的左兒子為空,只需要把新樹的根掛在根的右兒子的左兒子上,最後更新資訊即可

操作2:刪除

還是先提取區間,斷開根的右兒子與它的左兒子相連的邊就行,但這道題的空間有限,需要**節點編號,最好開個棧來存編號,用佇列的話有點浪費空間,而且必須開很大的陣列才能在codevs上ac,在洛谷上好像區別不大,當然我說的佇列是手寫佇列,你用stl我也沒話說

操作3:修改

同樣是先提取區間,把根的右兒子的左兒子修改後打上標記即可

操作4:翻轉

提取區間,把根的右兒子的左兒子修改後打上標記

操作5:求和

提取區間,輸出

操作6:求和最大的子串行的和

終於不用提取區間了,直接輸出就行。但維護資訊的時候很麻煩,與線段樹求和最大的子列類似,我們需要維護區間的子串行最大值,以及左右區間的最大子串行的和,在向上更新的時候,需要像下面這樣操作, 其中ls是x的左兒子,rs是右兒子,

mx是和最大子串行的和,lx是左區間最大子串行的和,rx是右區間最大子串行的和

細節:0號節點的mx要賦負無窮,因為有些點沒有左兒子或右兒子,避免更新答案時出錯(大導演wys這個細節調了1個小時)

標記下傳的時候要注意有沒有左兒子或右兒子,不然會改變0號節點的資訊,我搞了半個小時

伸展操作(splay)不要寫掛了,我搞了1個小時

**:

#includeusing

namespace

std;

const

int maxn = 500005, inf = 0x3f3f3f3f

;template

void read(t &re)

intn, m, root, id[maxn], tot;

inta[maxn];

struct

splay_tree

void

clear()

}tr[maxn];

intstak[maxn], top;

void update(int

x)void spread(int

x)

if(rs)

tr[x].c =inf;

tr[x].tag = 0

; }

if(tr[x].tag)

if(rs)

tr[x].tag = 0

; }

}void rotate(int

x)void splay(int x, int

to) rotate((tr[y].s[

1] == x) != (tr[z].s[1] == y) ?x: y);

rotate(x);

}if(!to)

root =x;

}int find(intx)}

void build(int l, int r, int

f)void insert(int pos, int

len)

void recycle( int

x)void del(int pos, int

len)

void change(int pos, int len, int

val)

void rever(int pos, int

len)

}int query(int pos, int

len)

intmain()

else

if(opt[0] == 'd'

)

else

if(opt[0] == '

m' && opt[2] == 'k'

)

else

if(opt[0] == 'r'

)

else

if(opt[0] == 'g'

)

else

printf(

"%d\n

", tr[root].mx);

}return0;

}

view code

noi2005維護數列

請寫乙個程式,要求維護乙個數列,支援以下 6 種操作 請注意,格式欄 中的下劃線 表示實際輸入檔案中的空格 操作編號 輸入檔案中的格式 說明1.插入 insert posi tot c1 c2 c tot 在當前數列的第 posi 個數字後插入 tot 個數字 c1,c2,c tot 若在數列首插 ...

NOI2005 維護數列

陳年老題。我就 碼了4k多。主要就是用splay,然後處理區間上的東西 區間反轉就和模板一樣,但是要記得反轉leftmax和rightmax 區間賦值就把那個區間提取出來,然後給子樹根打個same標記,表示下面的全一樣。區間求最大子段和就和線段樹的套路一樣。區間插入就先弄好一顆平衡樹,然後把原平衡樹...

NOI2005 維護數列

傳送門 我還是沒有逃過在這道題上debug好久的命運 我是使用 fhq treap 來做的這道題。寫的時候寫的挺爽的 調的時候真難受。首先我們先來說說咋做吧。前5個操作對於 fhq treap 來說不在話下,只要多打兩個標記就可以了。但是如何求最大子段和?於是乎我們再打三個標記來維護它 霧 然後我們...