(右偏树)Bzoj2333: [SCOI2011]棘手的操作

Posted Cyhlnj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(右偏树)Bzoj2333: [SCOI2011]棘手的操作相关的知识,希望对你有一定的参考价值。

题面

戳我

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]棘手的操作的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ2333][SCOI2011]棘手的操作

[bzoj 2333] 棘手的操作[SCOI2011]

bzoj2333[SCOI2011]棘手的操作 洛谷P3273 [SCOI2011]棘手的操作

bzoj2333 SCOI2011—棘手的操作

bzoj千题计划217:bzoj2333: [SCOI2011]棘手的操作

[bzoj2333][SCOI2011][棘手的操作]