Parity game

题目

有一个长度为n的序列
给出Q条限制
l,r,str str==odd 表示[l,r]区间内的数的和是奇数,否则为偶数
请你输出最小的不满足条件的编号-1(即最后一个满足的),如果全部满足,输出总数Q!

分析

算是一个带权并查集的模板题。dis[i]记录他到根结点的距离,假如a,b现在已经加入并查集了,现在要查询a,b之间的奇偶,只需要abs(dis[a]-dis[b]),然后拿此结果与当前answer进行比较就行了。不匹配,就break。

坑点:c++的取余可以是负数,在比较奇偶时加上绝对值

AC代码

#include <iostream>
#include <algorithm>
#include <map>
#include <stdio.h>
#include <string>
using namespace std;

int N,M;
map<int,int> fa,dis;

int find(int x){
    if(x != fa[x]) {
        int f = fa[x];
        fa[x] = find(fa[x]);
        dis[x] += dis[f];
    }
    return fa[x];
}
void join(int x,int y,int v){
    int fx = find(x),fy = find(y);
    if(fx != fy){
        fa[fx] = fy;
        dis[fx] = dis[y]+v-dis[x];
    }
}
int main(){
    cin>>N>>M;
    int a,b,v,res =0;string s;
    while(M--){
        scanf("%d %d",&a,&b);b++;
        if(!dis.count(a)) {
            dis[a] = 0;
            fa[a] = a;
        }
        if(!dis.count(b)) {
            dis[b] = 0;
            fa[b] = b;
        }
        cin>>s;
        if(s == "even") v = 0;
        else v = 1;
        if(find(a) == find(b)){
            if(abs((dis[a]-dis[b])%2) != v){ //注意要取绝对值
                break;
            }
        }else{
            join(a,b,v);
        }
        res++;
    }
    cout<<res<<endl;

    return 0;
}