题解 [SNOI2022] 垃圾回收

传送门

难点在于相信这是一道普及题(指 普及+/提高)
然后化加为删并查集随便搞搞就好了

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1000010
#define fir first
#define sec second
#define pb push_back
#define ll unsigned long long
//#define int long long

int n, m, q;
ll a[N];
int x[N];
char op[N], s[10];
pair<int, int> e[N];

namespace force{
	int dsu[N];
	ll tim[N], ans;
	bool vis[N], del[N];
	inline int find(int p) {return dsu[p]==p?p:dsu[p]=find(dsu[p]);}
	void solve() {
		for (int i=1; i<=q; ++i) {
			if (op[i]=='D') del[x[i]]=1;
			else {
				for (int j=1; j<=n; ++j) dsu[j]=j;
				for (int j=1; j<=m; ++j) if (!del[j]) dsu[find(e[j].fir)]=find(e[j].sec);
				for (int j=1; j<=n; ++j) if (find(j)!=find(1) && !vis[j]) vis[j]=1, tim[j]=i;
			}
		}
		for (int i=1; i<=n; ++i) if (!tim[i]) tim[i]=q+1;
		// cout<<"tim: "; for (int i=1; i<=n; ++i) cout<<tim[i]<<' '; cout<<endl;
		for (int i=1; i<=n; ++i) ans+=a[i]*tim[i];
		printf("%lld\n", ans);
	}
}

namespace task1{
	bool vis[N];
	ll tim[N], ans;
	int dsu[N], siz[N];
	vector<int> del[N], sub[N];
	inline int find(int p) {return dsu[p]==p?p:dsu[p]=find(dsu[p]);}
	inline void uni(int s, int t) {
		if ((s=find(s))==(t=find(t))) return ;
		if (siz[s]<siz[t]) swap(s, t);
		siz[dsu[t]=s]+=siz[t];
		for (auto& it:sub[t]) sub[s].pb(it);
	}
	void solve() {
		for (int i=1; i<=n; ++i) siz[dsu[i]=i]=1, sub[i].pb(i);
		for (int i=1; i<=q; ++i) if (op[i]=='D') vis[x[i]]=1;
		for (int i=1; i<=m; ++i) if (!vis[i]) uni(e[i].fir, e[i].sec);
		for (int i=1; i<=n; ++i) if (find(i)==find(1)) tim[i]=q+1;
		int lst=q+1;
		for (int i=q,s,t; i; --i) {
			if (op[i]=='D') {
				if ((s=find(e[x[i]].fir))==(t=find(e[x[i]].sec))) continue;
				if (s==find(1)||t==find(1)) {
					if (s!=find(1)) swap(s, t);
					for (auto& it:sub[t]) assert(!tim[it]), tim[it]=lst;
				}
				uni(s, t);
			}
			else lst=i;
		}
		for (int i=1; i<=n; ++i) if (!tim[i]) tim[i]=lst;
		// cout<<"tim: "; for (int i=1; i<=n; ++i) cout<<tim[i]<<' '; cout<<endl;
		for (int i=1; i<=n; ++i) ans+=a[i]*tim[i];
		printf("%llu\n", ans);
	}
}

signed main()
{
// 	freopen("garbage.in", "r", stdin);
// 	freopen("garbage.out", "w", stdout);

	scanf("%d%d%d", &n, &m, &q);
	for (int i=1; i<=m; ++i) scanf("%d%d", &e[i].fir, &e[i].sec);
	for (int i=1; i<=q; ++i) {
		scanf("%s", s), op[i]=*s;
		if (*s=='D') scanf("%d", &x[i]);
	}
	for (int i=1; i<=n; ++i) scanf("%lld", &a[i]);
	// force::solve();
	task1::solve();
	
	return 0;
}
posted @   Administrator-09  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示