列表

详情


NC20282. [SCOI2011]棘手的操作

描述

有N个节点,标号从1到N,这N个节点一开始相互不连通。第i个节点的初始权值为a[i],接下来有如下一些操作:
U x y: 加一条边,连接第x个节点和第y个节点
A1 x v: 将第x个节点的权值增加v
A2 x v: 将第x个节点所在的连通块的所有节点的权值都增加v
A3 v: 将所有节点的权值都增加v
F1 x: 输出第x个节点当前的权值
F2 x: 输出第x个节点所在的连通块中,权值最大的节点的权值
F3: 输出所有节点中,权值最大的节点的权值

输入描述

输入的第一行是一个整数N,代表节点个数。
接下来一行输入N个整数,a[1], a[2], …, a[N],代表N个节点的初始权值。
再下一行输入一个整数Q,代表接下来的操作数。
最后输入Q行,每行的格式如题目描述所示

输出描述

对于操作F1, F2, F3,输出对应的结果,每个结果占一行。

示例1

输入:

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

输出:

-10
10
10

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++11) 解法, 执行用时: 456ms, 内存消耗: 76216K, 提交时间: 2020-11-04 16:02:59

/*
U  x y:合并他们的两个堆

A1 x v:先pop到del,再push回val

A2 x v:连通块的变量处理

A3 x v:全局变量处理

F1 x:找到所属连通块,加上局部和全局变量

F2 x:直接pop

F3 x:整体的pop
*/
#include<bits/stdc++.h>

#define ll long long

using namespace std;

const int N=3e5+10;

int n,zt,m;
ll a[N],jub[N];int f[N];

vector<int>num[N];
//连通块里的点
struct nkl
{
	priority_queue<ll>q,del;

	void push(ll x){q.push(x);}
	void pop(ll x){del.push(x);}
	int top()
	{
		while(del.size()&&del.top()==q.top())
			del.pop(),q.pop();
		return q.top();
	}
}wl,bl[N];

inline int find(int x)
{
	if(x==f[x]) return x;
	return f[x]=find(f[x]);
}

int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		f[i]=i;//并查集初始化
		num[i].push_back(i);//连通块的点
		wl.push(a[i]);
		bl[i].push(a[i]);
		//全局与局部的点 
	}

	scanf("%d",&m);char ins[5];int x,v;
	while(m--)
	{
		scanf("%s",ins);
		if(ins[0]=='U')
		{
			scanf("%d%d",&x,&v);
			x=find(x),v=find(v);
			if(x==v) continue;

			if(num[x].size()<num[v].size()) swap(x,v);
			wl.pop(bl[v].top()+jub[v]);
			wl.pop(bl[x].top()+jub[x]);
			int len=num[v].size();
			for (int i=0;i<len;i++)
			{
				int j=num[v][i];
				f[j]=x;
				a[j]=a[j]+jub[v]-jub[x];
				bl[x].push(a[j]);
				num[x].push_back(j);
			}//开始合并
			num[v].clear();
			wl.push(bl[x].top()+jub[x]);
			//重回最大值
		}
		else if(ins[0]=='A')
		{
			if(ins[1]=='1')
			{
				scanf("%d%d",&x,&v);
				int u=find(x);
				wl.pop(bl[u].top()+jub[u]);
				bl[u].pop(a[x]);
				a[x]+=v;
				bl[u].push(a[x]);
				wl.push(bl[u].top()+jub[u]);
			}
			else if(ins[1]=='2')
			{
				scanf("%d%d",&x,&v);int u=find(x);
				wl.pop(bl[u].top()+jub[u]);
				jub[u]+=v;
				wl.push(bl[u].top()+jub[u]);
			}
			else scanf("%d",&v),zt+=v;
		}
		else
		{
			if(ins[1]=='3')
				printf("%lld\n",wl.top()+(ll)zt);
			else
			{
				scanf("%d",&x);
				int u=find(x);
				if(ins[1]=='1')
					printf("%lld\n",(ll)a[x]+zt+jub[u]);
				else
					printf("%lld\n",(ll)bl[u].top()+zt+jub[u]);
			}
		}
	}
	
	return 0;
}

上一题