• (右偏树)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
    ", 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
    ", t[rt[fx]].val + add);
    			else printf("%d
    ", Q.Top() + add);
    		}
    	}
        return 0;
    }
    
    
  • 相关阅读:
    ASP.NET实现进度条效果【转】
    删除指定创建日期前的文件夹、文件
    MS SQL SERVER执行大脚本文件时,提示“内存不足”的解决办法
    solr之functionQuery(函数查询)【转】
    解决Jenkins连接git时报错Permission denied (publickey)
    vscode csharp c#开发 自动引入命名空间
    nginx配置后外网无法访问
    jenkins node 版本无法使用最新的版本
    jenkins npm install WARN checkPermissions Missing write access 权限问题
    小程序setData只修改对象中的某个属性的方法
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8277682.html
Copyright © 2020-2023  润新知