题解 Q0Y1NzFE

传送门

采取启发式合并维护建出两棵树高为log的树
那么用其中一棵我们可以知道这个点最晚一次被置零是什么时候
用另一棵可以在每个节点上二分出在这一次置零之后的贡献
于是就做完了

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

inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, m;
char typ[10];

// namespace force{
// 	ll a[N];
// 	struct dsu{
// 		int fa[N], siz[N];
// 		set<int> s[N];
// 		void init() {for (int i=1; i<=n; ++i) fa[i]=i, siz[i]=1, s[i].insert(i);}
// 		inline int find(int p) {return fa[p]==p?p:fa[p]=find(fa[p]);}
// 		void uni(int a, int b) {
// 			a=find(a); b=find(b);
// 			if (a==b) return;
// 			siz[a]+=siz[b];
// 			fa[b]=a;
// 			for (auto it:s[b]) s[a].insert(it);
// 		}
// 		void add(int x) {
// 			x=find(x);
// 			for (auto it:s[x]) a[it]+=siz[x];
// 		}
// 		void zero(int x) {
// 			x=find(x);
// 			for (auto it:s[x]) a[it]=0;
// 		}
// 	}s1, s2;
// 	void solve() {
// 		s1.init(); s2.init();
// 		for (int i=1,x,y; i<=m; ++i) {
// 			scanf("%s", typ);
// 			if (*typ=='U') {
// 				x=read(); y=read();
// 				s1.uni(x, y);
// 			}
// 			else if (*typ=='M') {
// 				x=read(); y=read();
// 				s2.uni(x, y);
// 			}
// 			else if (*typ=='A') {
// 				x=read();
// 				s1.add(x);
// 			}
// 			else if (*typ=='Z') {
// 				x=read();
// 				s2.zero(x);
// 			}
// 			else {
// 				x=read();
// 				printf("%lld\n", a[x]);
// 			}
// 		}
// 		exit(0);
// 	}
// }
// 
// namespace task1{
// 	int op[N], x[N], y[N], top, k;
// 	ll a[N], sta[N];
// 	struct dsu1{
// 		int fa[N], siz[N], del[N];
// 		vector<pair<int, int>> buc[N];
// 		vector<ll> suf[N];
// 		void init() {for (int i=1; i<=n; ++i) fa[i]=i, siz[i]=1;}
// 		inline int find(int p) {return fa[p]==p?p:find(fa[p]);}
// 		void uni(int a, int b, int tim) {
// 			a=find(a); b=find(b);
// 			if (a==b) return ;
// 			if (siz[a]<siz[b]) swap(a, b);
// 			siz[a]+=siz[b];
// 			fa[b]=a; del[b]=tim;
// 		}
// 		void add(int x, int tim) {
// 			x=find(x);
// 			buc[x].pb({tim, siz[x]});
// 		}
// 		void prep_query() {
// 			for (int i=1; i<=n; ++i) {
// 				// cout<<"i: "<<i<<endl;
// 				top=0;
// 				for (int j=buc[i].size()-1; ~j; --j) sta[++top]=buc[i][j].sec;
// 				for (int j=1; j<=top; ++j) sta[j]+=sta[j-1];
// 				// cout<<"top: "<<top<<' '<<sta[top]<<endl;
// 				while (top) suf[i].pb(sta[top--]);
// 			}
// 		}
// 		ll query(int x, int tim) {
// 			int pre=tim, tem;
// 			ll ans=0;
// 			while (1) {
// 				if (lower_bound(buc[x].begin(), buc[x].end(), make(pre, 0))!=buc[x].end()) {
// 					// cout<<"x: "<<x<<endl;
// 					tem=lower_bound(buc[x].begin(), buc[x].end(), make(pre, 0))-buc[x].begin();
// 					// cout<<"tem: "<<tem<<endl;
// 					// cout<<"size: "<<buc[x].size()<<' '<<suf[x].size()<<endl;
// 					ans+=suf[x][tem];
// 				}
// 				if (fa[x]==x) break;
// 				pre=max(pre, del[x]); x=fa[x];
// 			}
// 			return ans;
// 		}
// 	}s1;
// 	struct dsu2{
// 		int fa[N], siz[N], lst[N], del[N];
// 		void init() {for (int i=1; i<=n; ++i) fa[i]=i, siz[i]=1;}
// 		inline int find(int p) {return fa[p]==p?p:find(fa[p]);}
// 		void uni(int a, int b, int tim) {
// 			a=find(a); b=find(b);
// 			if (a==b) return ;
// 			if (siz[a]<siz[b]) swap(a, b);
// 			siz[a]+=siz[b];
// 			fa[b]=a; del[b]=tim;
// 		}
// 		void zero(int x, int tim) {
// 			x=find(x);
// 			lst[x]=tim;
// 		}
// 		int query(int x) {
// 			int pre=0, ans=0;
// 			while (1) {
// 				if (lst[x]>pre) ans=max(ans, lst[x]);
// 				if (fa[x]==x) break;
// 				pre=del[x]; x=fa[x];
// 			}
// 			return ans;
// 		}
// 	}s2;
// 	void solve() {
// 		s1.init(); s2.init();
// 		for (int i=1; i<=m; ++i) {
// 			scanf("%s", typ);
// 			if (*typ=='U') {op[i]=1; x[i]=read(); y[i]=read(); k=i;}
// 			else if (*typ=='M') {op[i]=2; x[i]=read(); y[i]=read(); k=i;}
// 			else if (*typ=='A') {op[i]=3; x[i]=read(); k=i;}
// 			else if (*typ=='Z') {op[i]=4; x[i]=read(); k=i;}
// 			else {op[i]=5; x[i]=read();}
// 		}
// 		for (int i=1; i<=k; ++i) {
// 			if (op[i]==1) s1.uni(x[i], y[i], i);
// 			else if (op[i]==2) s2.uni(x[i], y[i], i);
// 			else if (op[i]==3) s1.add(x[i], i);
// 			else if (op[i]==4) s2.zero(x[i], i);
// 			else puts("error");
// 		}
// 		s1.prep_query();
// 		for (int i=k+1; i<=m; ++i) {
// 			assert(op[i]==5);
// 			// cout<<"tim: "<<s2.query(x[i])<<endl;
// 			printf("%lld\n", s1.query(x[i], s2.query(x[i])));
// 		}
// 		exit(0);
// 	}
// }

namespace task1{
	int op[N], x[N], y[N], top, k;
	ll a[N], sta[N];
	struct dsu1{
		int fa[N], siz[N], del[N];
		vector<pair<int, int>> buc[N];
		vector<ll> sum[N];
		void init() {for (int i=1; i<=n; ++i) fa[i]=i, siz[i]=1;}
		inline int find(int p) {return fa[p]==p?p:find(fa[p]);}
		void uni(int a, int b, int tim) {
			a=find(a); b=find(b);
			if (a==b) return ;
			if (siz[a]<siz[b]) swap(a, b);
			siz[a]+=siz[b];
			fa[b]=a; del[b]=tim;
		}
		void add(int x, int tim) {
			x=find(x);
			buc[x].pb({tim, siz[x]});
			sum[x].pb(siz[x]);
			if (sum[x].size()>1) sum[x][sum[x].size()-1]+=sum[x][sum[x].size()-2];
		}
		ll query(int x, int tim) {
			int pre=tim, tem;
			ll ans=0;
			while (1) {
				if (lower_bound(buc[x].begin(), buc[x].end(), make(pre, 0))!=buc[x].end()) {
					// cout<<"x: "<<x<<endl;
					tem=lower_bound(buc[x].begin(), buc[x].end(), make(pre, 0))-buc[x].begin();
					// cout<<"tem: "<<tem<<endl;
					// cout<<"size: "<<buc[x].size()<<' '<<suf[x].size()<<endl;
					// ans+=suf[x][tem];
					ans+=sum[x][sum[x].size()-1]-(tem>0?sum[x][tem-1]:0);
				}
				if (fa[x]==x) break;
				pre=max(pre, del[x]); x=fa[x];
			}
			return ans;
		}
	}s1;
	struct dsu2{
		int fa[N], siz[N], lst[N], del[N];
		void init() {for (int i=1; i<=n; ++i) fa[i]=i, siz[i]=1;}
		inline int find(int p) {return fa[p]==p?p:find(fa[p]);}
		void uni(int a, int b, int tim) {
			a=find(a); b=find(b);
			if (a==b) return ;
			if (siz[a]<siz[b]) swap(a, b);
			siz[a]+=siz[b];
			fa[b]=a; del[b]=tim;
		}
		void zero(int x, int tim) {
			x=find(x);
			lst[x]=tim;
		}
		int query(int x) {
			int pre=0, ans=0;
			while (1) {
				if (lst[x]>pre) ans=max(ans, lst[x]);
				if (fa[x]==x) break;
				pre=del[x]; x=fa[x];
			}
			return ans;
		}
	}s2;
	void solve() {
		s1.init(); s2.init();
		for (int i=1; i<=m; ++i) {
			scanf("%s", typ);
			if (*typ=='U') {op[i]=1; x[i]=read(); y[i]=read(); k=i;}
			else if (*typ=='M') {op[i]=2; x[i]=read(); y[i]=read(); k=i;}
			else if (*typ=='A') {op[i]=3; x[i]=read(); k=i;}
			else if (*typ=='Z') {op[i]=4; x[i]=read(); k=i;}
			else {op[i]=5; x[i]=read();}
		}
		for (int i=1; i<=m; ++i) {
			if (op[i]==1) s1.uni(x[i], y[i], i);
			else if (op[i]==2) s2.uni(x[i], y[i], i);
			else if (op[i]==3) s1.add(x[i], i);
			else if (op[i]==4) s2.zero(x[i], i);
			else printf("%lld\n", s1.query(x[i], s2.query(x[i])));
		}
		exit(0);
	}
}

signed main()
{
	n=read(); m=read();
	// force::solve();
	task1::solve();

	return 0;
}
posted @ 2021-12-19 21:37  Administrator-09  阅读(3)  评论(0编辑  收藏  举报