写在前面的

确实,题如其名,是一道实实在在的。在隔壁JK_Lover的指导下找到了一篇非常优秀的题解,并悟了一会儿。

思路

连边和连通性——可以通过并查集维护
点的查询和加权——用vector存储每一个连通块的点
连通块加权——打标记
合并——启发式合并,同时要更新标记
全局加——开个变量记录一下(这个操作真的拉胯,感觉一只哈士奇混入狼群)
局部以及全局的最大值——开个堆记录一下,需要支持可删除存在的元素,而且还需要支持可合并

这样就可以了呢。真的是一道呢(u1s1,这个思路相对于线段树,左偏树的写法又好理解代码量又少很多只是复杂度有一点点的高)。

代码

#include<bits/stdc++.h>
#define int long long
const int N=3e5+5,INF=0x3f3f3f3f,mod=998244353;
using namespace std;

int n,q,gtag;
int a[N],ltag[N],fa[N];
vector<int > num[N];

inline int read()
{
    register int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*f;
}

int find(int x){ return x==fa[x]?x:fa[x]=find(fa[x]);} 

struct node
{
    priority_queue<int > val,del;
    void push(int x){val.push(x);}
    void pop(int x){del.push(x);}
    int top(){while(del.size()&&val.top()==del.top()) val.pop(),del.pop();return val.top();}
}gmaxx,lmaxx[N];

signed main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
        fa[i]=i;
        num[i].push_back(i);
        lmaxx[i].push(a[i]);
        gmaxx.push(a[i]);
    }
    int q=read();
    while(q--)
    {
        char opt[5];
        scanf("%s",opt);
        if(opt[0]=='U')
        {
            int x,y;
            x=read();y=read();
            x=find(x);y=find(y);
            if(x!=y)
            {
                if(num[x].size()<num[y].size())    swap(x,y);
                gmaxx.pop(lmaxx[y].top()+ltag[y]);
                gmaxx.pop(lmaxx[x].top()+ltag[x]);
                for(int i=0;i<num[y].size();i++)
                {
                    int id=num[y][i];
                    fa[id]=x;
                    a[id]=a[id]+ltag[y]-ltag[x];
                    num[x].push_back(id);
                    lmaxx[x].push(a[id]);
                }
                num[y].clear();
                gmaxx.push(lmaxx[x].top()+ltag[x]);
            }
        }

        else if(opt[0]=='A')
        {
            if(opt[1]=='1')
            {
                int x,w;
                x=read();w=read();
                gmaxx.pop(lmaxx[find(x)].top()+ltag[find(x)]);
                lmaxx[find(x)].pop(a[x]);
                lmaxx[find(x)].push(a[x]+=w);
                gmaxx.push(lmaxx[find(x)].top()+ltag[find(x)]);
            }
            else if(opt[1]=='2')
            {
                int x,w;
                x=read();w=read();
                gmaxx.pop(lmaxx[find(x)].top()+ltag[find(x)]);
                ltag[find(x)]+=w;
                gmaxx.push(lmaxx[find(x)].top()+ltag[find(x)]);
            }
            else if(opt[1]=='3')
            {
                int w=read();
                gtag+=w;
            }
        }

        else if(opt[0]=='F')
        {
            if(opt[1]=='1')
            {
                int x=read();
                printf("%lld\n",a[x]+ltag[find(x)]+gtag);
            }
            else if(opt[1]=='2')
            {
                int x=read();
                printf("%lld\n",lmaxx[find(x)].top()+ltag[find(x)]+gtag);
            }
            else if(opt[1]=='3')
            {
                printf("%lld\n",gmaxx.top()+gtag);
            }
        }
    }
    return 0;
}