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