题意

  • 给定长为n的01串,给出m次描述,找出第一次矛盾的描述序号

思路

  • 将区间值转化为端点值
  • eg:[5,10]中有奇数个1,说明前4个数中1的个数和前10个数中1的奇偶性不同,也就是前4个数中有奇数个一的时候前10个数有偶数个1
  • 维护一个大小为2n的father数组,当属于1-n表明为奇数,属于n+1-2n表明为偶数,区间奇偶性不同就建边,奇偶性相同就在同区间建边
  • 直到出现矛盾或者全部通过

注意

  • 由于区间范围很大,不能开数组来存,需要使用map进行离散化
  • 由于使用map,需要用count方法来判断是否已经存在,如果不存在就赋初值使得父节点是自己
  • 如果存在就不用管

AC代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
map<int,int>fa;

int find(int x){
	return fa[x]==x?x:fa[x]=find(fa[x]);
}
void merge(int x,int y){
	fa[find(x)]=find(y);
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
    int n,m;
    cin>>n>>m;
    n+=5;
    int ans=m;
    for(int i=1;i<=m;i++){
        int a,b;
        cin>>a>>b;
        if (!fa.count(a-1)) {fa[a-1]=a-1;fa[a-1+n]=a-1+n;}
        if (!fa.count(b)) {fa[b]=b;fa[b+n]=b+n;}
        string s;
        cin>>s;
        if(s=="even"){
            if(find(a-1)==find(b+n)||find(a-1+n)==find(b)){
                ans=i-1;
                break;
            }else{
                merge(a-1,b);
                merge(a-1+n,b+n);
            }
        }else{
            if(find(a-1)==find(b)||find(a-1+n)==find(b+n)){
                ans=i-1;
                break;
            }else{
                merge(a-1,b+n);
                merge(a-1+n,b);
            }            
        }
    }
    cout<<ans<<'\n';
	return 0;
}