1. 程式人生 > >bzoj2333: [SCOI2011]棘手的操作

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); } } }