左偏树模拟。

记录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;
}
View Code