【bzoj3563】DZY Loves Chinese 在线cdq分治+并查集

和3237做法差不多,把cdq分治改成在线的就可以了。

至于怎么在线cdq分治?这个只可意会,不可言传。


#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#define maxn 500010

using namespace std;

struct yts
{
	int x,y;
	bool flag;
}e[maxn];

int ans[maxn],f[maxn],c[20];
int n,m,k,T;
char s[maxn];

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

bool check(char x)
{
	return x>='0' && x<='9';
}

int cal(int l,int r)
{
	int x=0;
	for (int i=l;i<=r;i++) x=x*10+s[i]-'0';
	return x;
}

int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=m;i++) scanf("%d%d",&e[i].x,&e[i].y);
	scanf("%d",&T);
	for (int i=1;i<=T;i++)
	{
		int kk,k=0;
		scanf("%d",&kk);
		gets(s+1);
		int len=strlen(s+1);
		for (int j=1;j<=len;j++)
		  if (check(s[j]) && !check(s[j+1])) k++;
		ans[i-1]=k^kk;
		if (i==T) 
		{
			for (int j=1;j<=len;j++)
			  if (check(s[j]))
			  {
				int k=j;
				while (check(s[k])) k++;
				e[cal(j,k-1)^ans[i-1]].flag=1;
				j=k-1;
			  }
		}
	}
	for (int i=1;i<T;i++) if (ans[i]-ans[i-1]) printf("Connected\n"); else printf("Disconnected\n");
	for (int i=1;i<=n;i++) f[i]=i;
	for (int i=1;i<=m;i++)
	  if (!e[i].flag)
	  {
	  	int f1=find(e[i].x),f2=find(e[i].y);
	  	if (f1!=f2) f[f1]=f2;
	  }
	int num=f[1];
	for (int i=2;i<=n;i++) if (f[i]!=num) {printf("Disconnected\n");return 0;}
	printf("Connected\n");
	return 0;
}


你可能感兴趣的:(【bzoj3563】DZY Loves Chinese 在线cdq分治+并查集)