Selection Contest for Rookies 1 F Forced Online Queries Problem

考虑并查集按秩合并和暴力撤销 可以维护加边和删边的操作

考虑分块 详见 https://blog.csdn.net/weixin_44231553/article/details/100598481

时间复杂度 O(q*sqrt(q)*logn) 调一调参数可以过

我就是来贴个代码

#include<bits/stdc++.h>
 
using namespace std;
 
#define N 200005
#define B 5000
 
int f[N], sz[N], st[N][3], top, bot, n, q, i, L, R, j, ans[N], t[N], x, y, px, py;
set<pair<int,int> > a, b, c;
pair<int,int> e;
pair<int,int> E[N][2];
 
int find(int x)
{
	return x==f[x]?x:find(f[x]);
}
 
void addc(int x,int y)
{
	x=find(x),y=find(y);
	if (x==y) return;
	if (sz[x]<sz[y]) swap(x,y);
	f[y]=x;
	sz[x]+=sz[y];
}
 
void addb(int x,int y)
{
	x=find(x),y=find(y);
	if (x==y) return;
	if (sz[x]<sz[y]) swap(x,y);
	st[++top][0]=x;
	st[top][1]=sz[x];
	st[top][2]=y;
	f[y]=x;
	sz[x]+=sz[y];
}
 
int main (void)
{
	scanf("%d%d",&n,&q);
	for (i=1; i<=q; i+=B) {
		L=i; R=min(i+B-1,q);
		a.clear(),b.clear(),c.clear();
		for (j=L; j<=R; j++) {
			scanf("%d%d%d",&t[j],&x,&y);
			if (x>y) swap(x,y);
			E[j][0]=make_pair(x,y);
			x=x%n+1;
			y=y%n+1;
			if (x>y) swap(x,y);
			E[j][1]=make_pair(x,y);
			a.insert(E[j][0]);
			a.insert(E[j][1]);
		}
		for (j=1; j<L; j++) {
			if (t[j]==2) continue;
			e=E[j][ans[j]];
			if (a.find(e)==a.end()) {
				if (c.find(e)==c.end()) c.insert(e);
				else c.erase(e);
			}
			else {
				if (b.find(e)==b.end()) b.insert(e);
				else b.erase(e);
			}
		}
		for (j=1; j<=n; j++) f[j]=j,sz[j]=1;
        for (set<pair<int,int> >::iterator x=c.begin(); x!=c.end(); x++) {
        	px=(*x).first;
        	py=(*x).second;
        	addc(px,py);
		}
		top=bot=0;
		for (j=L; j<=R; j++) {
			if (t[j]==1) {
				ans[j]=ans[j-1];
				e=E[j][ans[j]];
				if (b.find(e)==b.end()) b.insert(e);
				else b.erase(e);
			}
			else {
				e=E[j][ans[j-1]];
				while (top!=bot) {
					sz[st[top][0]]=st[top][1];
					f[st[top][2]]=st[top][2];
					top--;
				}
		        for (set<pair<int,int> >::iterator x=b.begin(); x!=b.end(); x++) {
		        	px=(*x).first;
		        	py=(*x).second;
		        	addb(px,py);
				}
				ans[j]=find(e.first)==find(e.second);
			}
		}
	}
	for (i=1; i<=q; i++) if (t[i]==2) printf("%d",ans[i]);
 
	return 0;
}

  

posted @ 2020-04-25 19:25  chinakevin  阅读(24)  评论(0编辑  收藏