[NOI2005] 維護數列
阿新 • • 發佈:2021-09-03
成功從不會平衡樹的蒟蒻變成了會平衡樹的蒟蒻。
前言
這篇部落格是 \(\rm FHQ\ Treap\)。
說句閒話,研究平衡樹的最好方法是:A了這道題,祝你們成功(滑稽
題目
講解
沒什麼好說的,只是過了這道題很爽,想水一下部落格慶祝慶祝。
所有操作都是模板,確實沒什麼好講的,就講幾個細節吧。
-
記得回收空間。
-
Reverse
操作的時候除了交換左右兒子,還要記得交換左右最大子段和。 -
最大子段和不能為空集。
-
更新最大子段和的時候很有可能會用到 \(0\) 號點,所以要把 \(0\) 號點與最大子段和相關的東西賦值為 \(-\infty\)。
-
插入的時候先把插入的點建成一棵很平衡的樹再插入,這樣不開 \(O2\)
程式碼
大常數程式碼
//12252024832524 #include <cstdio> #include <cstring> #include <algorithm> #define TT template<typename T> using namespace std; typedef long long LL; const int MAXN = 500005; const int MOD = 1e9 + 7; int n,m; char opt[10]; LL Read() { LL x = 0,f = 1;char c = getchar(); while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();} return x * f; } TT void Put1(T x) { if(x > 9) Put1(x/10); putchar(x%10^48); } TT void Put(T x,char c = -1) { if(x < 0) putchar('-'),x = -x; Put1(x); if(c >= 0) putchar(c); } TT T Max(T x,T y){return x > y ? x : y;} TT T Min(T x,T y){return x < y ? x : y;} TT T Abs(T x){return x < 0 ? -x : x;} int rt; struct FHQ_Treap { int l,r,val,siz,s,rd;//左右兒子、權值、siz、區間和、om value int lz1;//區間賦值標記 int lz2;//翻轉標記 int lm,rm,ms;//左右及全域性最大子段和 }t[MAXN]; int q[MAXN],tl = 500000; unsigned long long lst = 233; int Rand() { lst *= 20050525; lst += 520123; return (int)(lst % MOD); } int newnode(int val) { int ret = q[tl--]; if(t[ret].l) q[++tl] = t[ret].l; if(t[ret].r) q[++tl] = t[ret].r; t[ret].lz1 = MOD; t[ret].lz2 = t[ret].l = t[ret].r = 0; t[ret].siz = 1; t[ret].lm = t[ret].rm = t[ret].ms = t[ret].s = t[ret].val = val; t[ret].rd = Rand(); return ret; } void rev(int x) { if(!x) return; t[x].lz2 ^= 1; swap(t[x].l,t[x].r); swap(t[x].lm,t[x].rm); } void fuzhi(int x,int val) { if(!x) return; t[x].lz1 = val; t[x].s = t[x].siz * val; t[x].val = val; t[x].lm = t[x].rm = t[x].ms = Max(val,t[x].s); } void down(int x) { if(t[x].lz1^MOD) fuzhi(t[x].l,t[x].lz1),fuzhi(t[x].r,t[x].lz1),t[x].lz1 = MOD; if(t[x].lz2) rev(t[x].l),rev(t[x].r),t[x].lz2 = 0; } void up(int x) { t[x].siz = t[t[x].l].siz + t[t[x].r].siz + 1; t[x].s = t[t[x].l].s + t[t[x].r].s + t[x].val; t[x].lm = t[t[x].l].lm; t[x].lm = Max(t[x].lm,t[t[x].l].s + t[x].val + Max(0,t[t[x].r].lm)); t[x].rm = t[t[x].r].rm; t[x].rm = Max(t[x].rm,t[t[x].r].s + t[x].val + Max(0,t[t[x].l].rm)); t[x].ms = Max(t[t[x].l].ms,t[t[x].r].ms); t[x].ms = Max(t[x].ms,Max(t[x].lm,t[x].rm)); t[x].ms = Max(t[x].ms,t[x].val+Max(0,t[t[x].l].rm)+Max(0,t[t[x].r].lm)); } void split(int now,int val,int &x,int &y) { if(!now) {x = y = 0;return;} down(now); if(t[t[now].l].siz+1 <= val) { x = now; split(t[now].r,val-t[t[now].l].siz-1,t[now].r,y); } else { y = now; split(t[now].l,val,x,t[now].l); } up(now); } int mge(int x,int y) { if(!x || !y) return x|y; if(t[x].rd < t[y].rd) { down(x); t[x].r = mge(t[x].r,y); up(x); return x; } else { down(y); t[y].l = mge(x,t[y].l); up(y); return y; } } void recycle(int x){q[++tl] = x;} int a[MAXN]; int Build(int l,int r) { if(l > r) return 0; int mid = (l+r) >> 1; int now = newnode(a[mid]); t[now].l = Build(l,mid-1); t[now].r = Build(mid+1,r); up(now); return now; } int main() { // freopen("P2042_2.in","r",stdin); // freopen("mine.out","w",stdout); t[0].lm = t[0].rm = t[0].ms = -MOD; for(int i = 1;i <= tl;++ i) q[i] = i; n = Read(); m = Read(); for(int i = 1;i <= n;++ i) rt = mge(rt,newnode(Read())); int x,y,z; while(m --> 0) { scanf("%s",opt); if(opt[0] == 'I') { int pos = Read(),len = Read(); split(rt,pos,x,y); for(int i = 1;i <= len;++ i) a[i] = Read(); rt = mge(mge(x,Build(1,len)),y); } else if(opt[0] == 'D') { int pos = Read(),len = Read(); split(rt,pos-1,x,y); split(y,len,y,z); rt = mge(x,z); recycle(y); } else if(opt[2] == 'K') { int pos = Read(),len = Read(); split(rt,pos-1,x,y); split(y,len,y,z); fuzhi(y,Read()); rt = mge(mge(x,y),z); } else if(opt[0] == 'R') { int pos = Read(),len = Read(); split(rt,pos-1,x,y); split(y,len,y,z); rev(y); rt = mge(mge(x,y),z); } else if(opt[0] == 'G') { int pos = Read(),len = Read(); split(rt,pos-1,x,y); split(y,len,y,z); Put(t[y].s,'\n'); rt = mge(mge(x,y),z); } else if(opt[2] == 'X') Put(t[rt].ms,'\n'); } return 0; }