2019 UESTC ACM Training for Data Structures[K](并查集解决条件冲突问题)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/getsum/article/details/91042221

题目大意:现在给你一个n长度的串,然后n次询问及回答,在第x至第y位中元素的和 是奇数或是偶数。问从哪一次开始,下一次的回答与之前的是矛盾的。也就是找第一次与前面的条件发冲突的条件,其中 even为偶数 odd为奇数

带权并查集和dp。如果L-R的和为偶数,即可看作区间内有偶数个1,其他的都为零。如果L-R的和为奇数,即可看作区间内有奇数个1,其他的都为零。
因此我们用前缀和val[i]表示前i个数的奇偶情况。val[i]=0和1分别对应前i个数的和为偶数和奇数的情况。
进行分析:
对于1-i个数,1<=j<=i,如果i-j为偶数个1,那么val[i]=val[j-1] (即同奇偶性),即val[j-1]^val[i]=0
如果i~j为奇数个1,那么val[i]!=val[j-1] (即相反奇偶性),即val[j-1]^val[i]=1
当当前区间能和之前区间组成连续区间的时候要进行合并,并且维护节点权值,因此用带权并查集。
当当前区间已经加入集合,就判断是否和之前的条件相悖

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#define LL long long
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e6+5;
int n,m,num,fa[maxn],val[maxn];
char inp[10];
int getfa(int x){
	if(x!=fa[x]){
		int t=getfa(fa[x]);
		val[x]^=val[fa[x]];
		return fa[x]=t;
	}
	return fa[x];
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)fa[i]=i;
	for(int i=1;i<=m;i++){
		int x,y;
		scanf("%d%d%s",&x,&y,inp);
		x--;
		num= inp[0]=='o';
	//	cout<<x<<" "<<y<<" "<<num<<"~~~~~~~~~~~~~~~~~"<<endl;
		int fx=getfa(x),fy=getfa(y);
		if(fx!=fy)fa[fy]=fx,val[fy]=val[y]^val[x]^num;
		else if((val[x]^val[y])!=num){
			printf("%d",i-1);
			return 0;
		}
	}
	puts("ORZQHQH");
	
}

猜你喜欢

转载自blog.csdn.net/getsum/article/details/91042221