(右偏树)Bzoj2333: [SCOI2011]棘手的操作
2018-01-12 21:05
537 查看
题面
戳我Sol
右偏树滑稽+并查集再在全局开一个可删除的堆(priority_queue)
注意细节
# include <bits/stdc++.h> # define RG register # define IL inline # define Fill(a, b) memset(a, b, sizeof(a)) using namespace std; typedef long long ll; const int _(3e5 + 10); IL ll Read(){ RG ll x = 0, z = 1; RG char c = getchar(); for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1; for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48); return x * z; } int n, a[_], fa[_], add, S[_], top, rt[_]; struct Right_Heap{ int fa, ls, rs, dis, val, tag; } t[_]; struct Heap{ priority_queue <int> A, B; IL void Push(RG int x){ A.push(x); } IL void Del(RG int x){ B.push(x); } IL int Top(){ while(!B.empty() && A.top() == B.top()) A.pop(), B.pop(); return A.top(); } } Q; IL void Update(RG int x){ t[x].dis = t[t[x].ls].dis + 1; } IL void Adjust(RG int x){ if(t[t[x].ls].dis > t[t[x].rs].dis) swap(t[x].ls, t[x].rs); } IL void Add(RG int x, RG int d){ if(!x) return; t[x].tag += d; t[x].val += d; } IL void Pushdown(RG int x){ if(!t[x].tag) return; Add(t[x].ls, t[x].tag); Add(t[x].rs, t[x].tag); t[x].tag = 0; } IL int Find(RG int x){ return fa[x] == x ? x : fa[x] = Find(fa[x]); } IL int Merge(RG int x, RG int y){ if(!x || !y) return x + y; Pushdown(x); Pushdown(y); if(t[x].val < t[y].val) swap(x, y); RG int tmp = Merge(t[x].ls, y); t[tmp].fa = x; t[x].ls = tmp; Adjust(x); Update(x); return x; } IL void Pushall(RG int x){ for(RG int y = x; y; y = t[y].fa) S[++top] = y; while(top) Pushdown(S[top--]); } IL void Modify(RG int x, RG int d){ Pushall(x); RG int tmp = Merge(t[x].ls, t[x].rs); if(t[x].fa){ if(t[t[x].fa].ls == x) t[t[x].fa].ls = tmp; else t[t[x].fa].rs = tmp; for(RG int y = t[x].fa; y; y = t[y].fa) Adjust(y), Update(y); } t[tmp].fa = t[x].fa; t[x].fa = t[x].ls = t[x].rs = 0; RG int fx = Find(x); Q.Del(t[rt[fx]].val); if(x == rt[fx]) rt[fx] = tmp; t[x].val += d; rt[fx] = Merge(rt[fx], x); t[rt[fx]].fa = 0; Q.Push(t[rt[fx]].val); } IL void Query(RG int x){ Pushall(x); printf("%d\n", t[x].val + add); } int main(RG int argc, RG char* argv[]){ n = Read(); for(RG int i = 1; i <= n; ++i) t[i].val = Read(), Q.Push(t[i].val), fa[i] = rt[i] = i; for(RG int m = Read(); m; --m){ RG char op[5]; RG int x, y, fx, fy; scanf(" %s", op); if(op[0] == 'U'){ x = Read(); y = Read(); fx = Find(x); fy = Find(y); if(fx == fy) continue; Q.Del(t[rt[fx]].val); Q.Del(t[rt[fy]].val); fa[fx] = fy; rt[fy] = Merge(rt[fx], rt[fy]); t[rt[fy]].fa = 0; Q.Push(t[rt[fy]].val); } else if(op[0] == 'A'){ if(op[1] == '1') x = Read(), y = Read(), Modify(x, y); else if(op[1] == '2'){ x = Read(); y = Read(); fx = Find(x); Q.Del(t[rt[fx]].val); Add(rt[fx], y); Q.Push(t[rt[fx]].val); } else x = Read(), add += x; } else{ if(op[1] == '1') x = Read(), Query(x); else if(op[1] == '2') x = Read(), fx = Find(x), printf("%d\n", t[rt[fx]].val + add); else printf("%d\n", Q.Top() + add); } } return 0; }
相关文章推荐
- [BZOJ2333][SCOI2011][可并堆]棘手的操作
- bzoj 2333: [SCOI2011]棘手的操作(线段树+离线操作)
- 【BZOJ2333】【SCOI2011】棘手的操作
- 【BZOJ2333】棘手的操作(SCOI2011)-线段树+并查集+离线处理
- BZOJ 2333 【SCOI2011】 棘手的操作
- BZOJ 2333 SCOI 2011 棘手的操作 可并堆
- [bzoj2333] [SCOI2011]棘手的操作 (可并堆)
- BZOJ 2333 SCOI2011 棘手的操作 并查集+可并堆
- 【bzoj2333】[SCOI2011]棘手的操作 可并堆+STL-set
- BZOJ 2333 [SCOI2011]棘手的操作
- [BZOJ2333][SCOI2011]棘手的操作(可并堆||线段树+离线)
- (右偏树)Bzoj2333: [SCOI2011]棘手的操作
- 【BZOJ2333】【SCOI2011】棘手的操作 treap合并
- [可并堆] BZOJ 2333 [SCOI2011]棘手的操作
- 【BZOJ 2333 】[SCOI2011]棘手的操作(离线+线段树|可并堆-左偏树)
- 【bzoj2333】 SCOI2011—棘手的操作
- 【左偏树】【bzoj 2333】: [SCOI2011]棘手的操作
- [BZOJ2333][SCOI2011]棘手的操作(可并堆||线段树)
- BZOJ 2333 SCOI2011 棘手的操作 可并堆套可并堆
- [bzoj2333][SCOI2011][棘手的操作]