题目链接
题意
一个只含01的串,告诉你a-b的1的个数的奇偶性,问第几句话开始矛盾
思路
带权并查集,va数组表示父父节点间存在的1的个数的奇偶性,因为n太大了所以需要离散化。离散化学了没咋用过,带权并查集几天不写又全忘了,wa到头疼,思路没难度,之前博客写过类似题,注释多写了些,看代码吧,不懂可以翻翻我之前的带权并查集博客。
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<map>
#include<string>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
using namespace std;
typedef long long ll;
const int maxn=50500;//别问,问就是开越大越好 ^^
const int inf=0x3f3f3f3f;
int fa[maxn];
int va[maxn];//1奇数,0偶数
int a[maxn],b[maxn];//b数组没用,懒得删了
struct Node{
int x,y,z;
}node[maxn];//离线操作,存一下
int n,q;
void init(){
for(int i=0;i<maxn;i++){
va[i]=0;//初始化为0,自己跟自己的1个数肯定为0,也就是偶数
fa[i]=i;
}
}
int find(int x){
if(x==fa[x])
return x;//直接返回
int t=find(fa[x]);
va[x]^=va[fa[x]];//va维护的是和父节点的关系,如果要路径压缩的话需要异或上父节点value
//至于为什么异或,0代表偶,1代表奇,自己模拟下就行了
return fa[x]=t;//路径压缩优化
}
void unite(int x,int y,int z){
int fx=find(x),fy=find(y);
if(fx==fy)
return ;
fa[fx]=fy;
va[fx]=va[x]^va[y]^z;//建议画图手推,可以看我第一篇带权并查集博客,有一张推find函数的思路图
}
int main(){
IOS
cin>>n>>q;
init();
int p=1;
for(int i=1;i<=q;i++){
int x,y;
cin>>x>>y;
x--;//xy包含端点,处理下x--或者y++
a[p]=x;
node[i].x=x;
p++;
a[p]=y;
node[i].y=y;
p++;
string s;
cin>>s;
if(s=="even")
node[i].z=0;
else
node[i].z=1;
}
//离散化部分
p--;
sort(a+1,a+1+p);
int len=unique(a+1,a+p+1)-a-1;
int ans=q;
for(int i=1;i<=q;i++){
int x=lower_bound(a+1,a+len+1,node[i].x)-a;
int y=lower_bound(a+1,a+len+1,node[i].y)-a;
int fx=find(x),fy=find(y);
if(fx!=fy)
unite(x,y,node[i].z);
else{
if(va[x]^va[y]!=node[i].z){
ans=i-1;
break;
}
}
}
cout<<ans<<endl;
}