bzoj2333: [SCOI2011]棘手的操作

题目
题解
set+左偏树

#include<bits/stdc++.h>
using namespace std;
const int N=300002;
int fa[N],l[N],r[N],x,y,w[N],add[N],d[N],n,i,m,rx,ry,v;
multiset<int>S;
char s[3];
#define gc getchar
inline int rd(){
	int x=0,fl=1;char ch=gc();
	for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
	for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
	return x*fl;
}
inline void wri(int a){if(a<0)a=-a,putchar('-');if(a>=10)wri(a/10);putchar(a%10|48);}
inline void wln(int a){wri(a),puts("");}
int find(int x){
	while (fa[x]) x=fa[x];
	return x;
}
void down(int x){
	if (add[x]) w[l[x]]+=add[x],w[r[x]]+=add[x],add[l[x]]+=add[x],add[r[x]]+=add[x],add[x]=0;
}
void update(int x){
	if (fa[x]) update(fa[x]);
	down(x);
}
int merge(int x,int y){
	if (!x || !y) return x+y;
	down(x),down(y);
	if (w[x]<w[y]) swap(x,y);
	r[x]=merge(r[x],y);fa[r[x]]=x;
	if (d[l[x]]<d[r[x]]) swap(l[x],r[x]);
	d[x]=d[r[x]]+1;
	return x;
}
int del(int x){
	int f=fa[x],t=merge(l[x],r[x]);
	fa[x]=l[x]=r[x]=0;
	if (x==l[f]) l[f]=t;
	else r[f]=t;
	fa[t]=f;
	return find(t);
}
void erase(int x){S.erase(S.find(x));}
int main(){
	n=rd();
	for (i=1;i<=n;i++) w[i]=rd(),S.insert(w[i]);
	d[0]=-1;
	for (m=rd();m--;){
		scanf("%s",s);
		if (s[0]=='U'){
			x=rd(),y=rd();
			rx=find(x),ry=find(y);
			if (rx==ry) continue;
			if (merge(rx,ry)==rx) erase(w[ry]);
			else erase(w[rx]);
		}
		if (s[0]=='A'){
			x=rd();
			if (s[1]=='1') y=rd(),update(x),erase(w[find(x)]),w[x]+=y,S.insert(w[merge(x,del(x))]);
			else if (s[1]=='2') y=rd(),rx=find(x),erase(w[rx]),S.insert(w[rx]+=y),add[rx]+=y;
			else v+=x;
		}
		if (s[0]=='F'){
			if (s[1]=='1') x=rd(),update(x),wln(w[x]+v);
			else if (s[1]=='2') x=rd(),wln(w[find(x)]+v);
			else wln(*(--S.end())+v);
		}
	}
}

猜你喜欢

转载自blog.csdn.net/xumingyang0/article/details/84951563