NOI2005 維護數列

2022-05-09 13:00:48 字數 1765 閱讀 5877

一道splay綜合大板子題。

題面:下面是題解:

首先對每個點維護這些量:

1.兩個兒子(ch[2])

2.父節點(fa)

3.當前點權值(vl)和子樹權值(sum)

4.修改標記(xg),反轉標記(fz)。

5.mx,mxl,mxr(不清楚的建議做小白逛公園)。

題中還有乙個條件,即:

100%的資料中,任何時刻數列中最多含有500 000個數。

這就解決了空間問題。我們可以用乙個佇列記錄有多少點可以**,這樣就可以節省大量的空間。

最後一點:本題中涉及到max值,區間反轉後需要update。

**:

#include#include

#include

using

namespace

std;

#define n 1000050

intn,m,a[n],rt,tot,pos,cnt,id[n];

queue

que;

char ch[15

];struct

splay

tr[n];

void update(int

u)void pushdown(int

u)else

}if(tr[u].fz)

}void rotate(int

x)void splay(int u,int

goal)

if(!goal)rt=u;

}void build(int l,int r,int

f)else

tr[u].vl =a[mid];

tr[u].fa =fa;

update(u);

tr[fa].ch[mid>=f] =u;

}int find(int x,int

k)void insert(int k,int

tt)

for(int i=1;i<=tt;i++)

else

}build(

1,tt,0

);

int rt0 = id[(1+tt)>>1

];

int l = find(rt,k+1

);

int r = find(rt,k+2

); splay(l,0);

splay(r,l);

tr[r].ch[

0]=rt0;

tr[rt0].fa=r;

update(r);

update(rt);

}void rip(int

x)int deal(int l,int

r)void erase(int l,int

r)void make_same(int l,int r,int

k)void rever(int l,intr)}

int get_sum(int l,int

r)int

main()

else

if(ch[0]=='d'

)

else

if(ch[2]=='k'

)

else

if(ch[0]=='r'

)

else

if(ch[0]=='g'

)

else

}return0;

}

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 來說不在話下,只要多打兩個標記就可以了。但是如何求最大子段和?於是乎我們再打三個標記來維護它 霧 然後我們...