左偏树模拟。
记录lazy[x],merge,A1与F1操作时要从堆顶向下pushdown
用multiset记录每个堆的堆顶元素,每次操作之后维护
http://www.lydsy.com/JudgeOnline/problem.php?id=2333
/************************************************************** Problem: 2333 User: 1349367067 Language: C++ Result: Accepted Time:3644 ms Memory:15304 kb ****************************************************************/ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<set> #define N 300011 using namespace std; multiset<int> Set; int n,ALL=0; int v[N]={},fa[N]={},l[N]={},r[N]={},dis[N]={}; int lazy[N]={}; void pushdown(int x) { if (lazy[x]==0) return; int t=lazy[x]; if (r[x])lazy[r[x]]+=t,v[r[x]]+=t; if (l[x])lazy[l[x]]+=t,v[l[x]]+=t; lazy[x]=0; return; } int merge(int x,int y) { if (x==0) return y; if (y==0) return x; if (v[x]<v[y]) swap(x,y); pushdown(x); r[x]=merge(r[x],y); fa[r[x]]=x; if (dis[r[x]]>dis[l[x]]) swap(l[x],r[x]); dis[x]=dis[r[x]]+1; return x; } /*int Q[N]={},tot=0; void pushup(int x) { tot=0; while (x) Q[++tot]=x,x=fa[x]; while (tot) pushdown(Q[tot--]); return; }*/ void pushup(int x) { if (fa[x]!=0) pushup(fa[x]); pushdown(x); } inline int findf(int x) { while (fa[x]) x=fa[x]; return x; } void init() { scanf("%d",&n); for (int i=1;i<=n;i++) { fa[i]=l[i]=r[i]=lazy[i]=dis[i]=0; scanf("%d",&v[i]),Set.insert(v[i]); } } void work() { int m; int x,y,q,p,t,f; char ch[10]; scanf("%d",&m); for (int i=1;i<=m;i++) { scanf("%s",ch); //cout<<"***"<<i<<" "<<ch[0]<<ch[1]<<endl; if (ch[0]=='U') { scanf("%d%d",&x,&y); q=findf(x);p=findf(y); if (q==p) continue; t=merge(q,p); if (q==t) Set.erase(Set.find(v[p])); else Set.erase(Set.find(v[q])); } if (ch[0]=='A'&&ch[1]=='1') { scanf("%d%d",&x,&y); pushup(x); q=findf(x); Set.erase(Set.find(v[q])); pushup(x); t=merge(l[x],r[x]);f=fa[x]; l[x]=r[x]=fa[x]=0; if (x==l[f]) l[f]=t; else r[f]=t; fa[t]=f;t=findf(t); v[x]+=y; Set.insert(v[merge(x,t)]); } if (ch[0]=='A'&&ch[1]=='2') { scanf("%d%d",&x,&y); q=findf(x); Set.erase(Set.find(v[q])); lazy[q]+=y;v[q]+=y; Set.insert(v[q]); } if (ch[0]=='A'&&ch[1]=='3') { scanf("%d",&y); ALL+=y; } if (ch[0]=='F'&&ch[1]=='1') { scanf("%d",&x); pushup(x); printf("%d\n",v[x]+ALL); } if (ch[0]=='F'&&ch[1]=='2') { scanf("%d",&x); q=findf(x); //cout<<x<<" * "<<q<<endl; printf("%d\n",v[q]+ALL); } if (ch[0]=='F'&&ch[1]=='3') { printf("%d\n",*--Set.find(1000000000)+ALL); } } } int main() { init(); work(); return 0; }