[bzoj2333] [SCOI2011] tricky operation can be paralleled + set

Posted by adige72 on Sun, 03 May 2020 02:50:34 +0200

Description

There are n nodes, labeled from 1 to N, which are disconnected from each other at the beginning. The initial weight of the ith node is a[i], and then there are some operations as follows:

U x y: add an edge to connect the x-th and y-th nodes

A1 x v: increase the weight of node X by v

A2 x v: increase the weight of all nodes in the connected block where the x-th node is located by v

A3 v: increase the weight of all nodes by v

F1 x: output the current weight of node x

F2 x: output the weight of the node with the largest weight in the connected block where the x-th node is located

F3: output the weight of the node with the largest weight among all nodes

Input

The first line of input is an integer N, representing the number of nodes.

Next, enter n integers, a[1], a[2] , a[N], representing the initial weight of N nodes.

Enter an integer Q on the next line to represent the next operand.

Finally, input line Q, the format of each line is as shown in the title description.

Output

For operations F1, F2, F3, output the corresponding results, each result occupies one line.

Sample Input

3
0 0 0
8
A1 3 -20
A1 2 20
U 1 3
A2 1 10
F1 3
F2 3
A3 -10
F3

Sample Output

-10
10
10

HINT

For 30% data, guarantee n < = 100, Q < = 10000

For 80% data, guarantee n < = 100000, Q < = 100000

For 100% data, guarantee n < = 300000, Q < = 300000

For all data, ensure that the input is legal and - 1000 < = V, a [1], a [2] , a[N]<=1000

Code

#include<bits/stdc++.h>
#define ll long long
#define inf 1000000000
#define mod 65537
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int N=300005;
int n,Q,add;
int a[N],q[N],fa[N],ls[N],rs[N],tag[N],tot;
multiset<int>s;
int find(int x)
{
    while (fa[x]) x=fa[x];
    return x;
}
void pushdown(int x)
{
    if(!tag[x])return;
    int t=tag[x],l=ls[x],r=rs[x];
    tag[x]=0;
    if(l)tag[l]+=t,a[l]+=t;
    if(r)tag[r]+=t,a[r]+=t;
}
int merge(int x,int y)
{
    if (!x) return y;
    if (!y) return x;
    if (a[x]<a[y]) swap(x,y);
    pushdown(x);
    rs[x]=merge(rs[x],y);
    fa[rs[x]]=x;
    swap(ls[x],rs[x]);
    return x;
}
void pushtag(int x)
{
    while(x)q[++tot]=x,x=fa[x]; 
    while(tot)pushdown(q[tot--]);
}
int del(int x)
{
    pushtag(x);
    int f=fa[x],t=merge(ls[x],rs[x]);
    ls[x]=rs[x]=fa[x]=0;
    if (x==ls[f]) ls[f]=t;else rs[f]=t;
    fa[t]=f;
    return find(t);
}
int main()
{
    n=read();for (int i=1;i<=n;i++) a[i]=read(),s.insert(a[i]);
    Q=read();
    while (Q--)
    {
        char ch[5];scanf("%s",ch);
        if (ch[0]=='U')
        {
            int x=find(read()),y=find(read());
            if (x!=y)
            {
                if (merge(x,y)==x)s.erase(s.find(a[y]));
                else s.erase(s.find(a[x]));
            }
        }
        else if (ch[0]=='A')
        {
            if (ch[1]=='1')
            {
                int x=read(),v=read();
                pushtag(x);s.erase(s.find(a[find(x)]));
                a[x]+=v;
                s.insert(a[merge(x,del(x))]);
            }
            else if (ch[1]=='2')
            {
                int x=read(),v=read(),f=find(x);
                tag[f]+=v;a[f]+=v;
                s.erase(s.find(a[f]-v));s.insert(a[f]);
            }
            else
            {
                int v=read();add+=v;
            }
        }
        else
        {
            if (ch[1]=='1')
            {
                int x=read();pushtag(x);printf("%d\n",a[x]+add);
            }
            else if (ch[1]=='2')
            {
                int x=read(),f=find(x);printf("%d\n",a[f]+add);
            }
            else printf("%d\n",*--s.find(inf)+add);
        }
    }
    return 0;
}