「poj 1733」Parity game (拆点并查集)

poj 1733
有字符串,由$0$和$1$组成,给出几个区间,并且告诉你区间里面$1$的个数的奇偶性,假设前面的话都是对的,问你到哪一句和前面的话矛盾。

这种题肯定想图论问题。
对于区间,转化为前缀和相减。那么前缀和奇偶性相不相同就能确定了。
若区间为奇数则奇偶性不同,否则奇偶性相同。
然后拆点并查集判关系即可。

对于区间,转化为前缀和相减

#include<cstdio> 
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<cmath>
#define ms(i, j) memset(i, j, sizeof i)
#define LL long long
#define db double
#define fir first
#define sec second
#define mp make_pair
using namespace std;

namespace flyinthesky {

    struct data {
        int l, r, x;
    } opt[5000 + 5];

    int m, q, whw[10000 + 5], gg; 
    int f[20000 + 5];

    int getRealID(int x) {return lower_bound(whw + 1, whw + 1 + gg, x) - whw;}
    int find(int x) {return f[x] == x ? x : f[x] = find(f[x]);}

    void clean() {
        gg = 0;
    }
    int solve() {
        clean();
        scanf("%d%d", &m, &q);
        for (int i = 1; i <= q; ++i) {
            char s[10]; scanf("%d%d%s", &opt[i].l, &opt[i].r, s);
            if (s[0] == 'e') opt[i].x = 0; else opt[i].x = 1;
            whw[++gg] = opt[i].l - 1, whw[++gg] = opt[i].r;
        }
        sort(whw + 1, whw + 1 + gg), gg = unique(whw + 1, whw + 1 + gg) - whw - 1;
        for (int i = 0; i <= 20000; ++i) f[i] = i;
        for (int i = 1; i <= q; ++i) {
            int x = find(getRealID(opt[i].l - 1)), y = find(getRealID(opt[i].r));
            int xn = find(getRealID(opt[i].l - 1) + gg), yn = find(getRealID(opt[i].r) + gg);
            if (x == y) { // 奇偶性相同 
                if (opt[i].x == 1) return printf("%d\n", i - 1), 0;
            } else if (x == yn) {
                if (opt[i].x == 0) return printf("%d\n", i - 1), 0;
            }
            if (opt[i].x == 0) f[x] = y, f[xn] = yn; else f[x] = yn, f[y] = xn;
        }
        printf("%d\n", q);
        return 0;
    }
}
int main() {
    flyinthesky::solve();
    return 0;
}
------ 本文结束 ------