NOI2005 維護數列

2022-08-01 17:54:12 字數 2687 閱讀 4345

輸入檔案的第 1 行包含兩個數 n 和 m,n 表示初始時數列中數的個數,m 表示要進行的運算元目。 第 2 行包含 n 個數字,描述初始時的數列。 以下 m 行,每行一條命令,格式參見問題描述中的**

對於輸入資料中的 get-sum 和 max-sum 操作,向輸出檔案依次列印結 果,每個答案(數字)佔一行。

你可以認為在任何時刻,數列中至少有 1 個數。

輸入資料一定是正確的,即指定位置的數在數列中一定存在。

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

100%的資料中,任何時刻數列中任何乙個數字均在[-1 000, 1 000]內。

100%的資料中,m ≤20 000,插入的數字總數不超過 4 000 000 。

序列翻轉基本操作

區間最大子段和

有了上面的鋪墊,其實這些操作都可以解決了。

以下的根不做特殊說明都指區間代表子樹的根。

只是有點小細節需要注意:

插入時要先把插入序列建splay,不然乙個乙個插入會超時。建splay時需要特判葉子節點維護一些資訊,對於lmax和rmax需要將val和0取max,因為在父親節點更新lmax是可能為左區間+父親節點本身,如果右區間lmax直接取val,就可能取不到這種情況,或許比較三種情況可以解決這個問題,但是很麻煩不是嗎。

刪除的時候,把這段區間提取出來刪除即可。不過因為空間原因需要**節點編號,所以需要遍歷這棵子樹**,用佇列裝編號。最多插入4e6個數,所以最多遍歷4e6個點。

區間覆蓋的時候,提取區間後,在根打上覆蓋標記,維護節點資訊:注意如果val是負數最大子段和賦成val。

翻轉提取區間,在根打上翻轉標記,將lmax和rmax交換。

求和提取區間輸出根的sum即可。

這道題的最大子段和是整個序列的,其實降低了一點難度,直接輸出整顆splay的根的最大子段和即可。

下傳在find裡面。

建初始序列時要在收尾插入兩個最小值,因為最大值在求最大子段和會有影響。

還有對於0號節點的最大子段和賦最小值,因為一些沒有兒子的點更新資訊會用到。

#includeusing

namespace

std;

const

int oo=1000000

;const

int maxn=500005

;int

n,m;

inta[maxn],num,id[maxn],root;

queue

q;struct

splaytr[maxn];

template

inline void read(t &x)

while(isdigit(ch))

x= f ? -x : x ;

}int max(int x,int y)

void update(splay &ret,splay lx,splay ry)

void update(int

x)int build(int l,int r,int

f) tr[now].s[

0]=build(l,mid-1

,now);

tr[now].s[

1]=build(mid+1

,r,now);

update(now);

return

now;

}void put_cover(int x,int

val)

void put_tag(int

x)void push_down(int

x)

if(tr[x].tag)

}void debug(int

x)int find(int

k) k-=tr[tr[now].s[0

]].size;

if(k==1) return

now;

k--;

now=tr[now].s[1

]; }

}int

get(int

x)void connect(int x,int y,int

d)void rotate(int

x)void splay(int x,int

go)

else

}}void

insert()

int nowroot=build(1,tot,0

);

int x=find(pos+1),y=find(pos+2

); splay(x,root);

splay(y,tr[x].s[

1]);

tr[nowroot].fa=y;

tr[y].s[

0]=nowroot;

update(y);

update(x);

}void clean(int

x),0,0,0,oo,0,0,0,0,0};}

void recycle(int

x)void

dele()

void

modify()

void

reverse()

intquerysum()

intquerydat()

intmain()

}

維護數列

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