Poj P1733 Parity game___带权并查集+hash

版权声明:欢迎借鉴,谢绝抄搬。 https://blog.csdn.net/Gx_Man_VIP/article/details/80516329

题目大意:

MLi,Ri,strstreven[Li,Ri]11N

N109
M104

分析:


①奇-偶=奇
②奇-奇=偶
③偶-偶=偶
所以,当
区间[L,R]1,即Sum[l,r]有偶数个,
那么显然Sum[l,r]=Sum[1,r]Sum[1,l1]
所以Sum[1,r]Sum[1,l1]的奇偶性相同
同理Sum[l,r]有奇数个,
那么Sum[1,r]Sum[1,l1]的奇偶性不同
那么我们可以考虑用带权并查集去做,
d[x]=0xfather
d[x]=1xfather
那么可以通过xor运算求出x与当前集合的树根z奇偶性
对于一个区间[l,r]Sum[l,r]
我们显然可以发现,当
l1r
l1xry
然后xy连边即可
可是这时候的d[x]

l1rSum[l,r]
l1xdl1
rydr
那么显然可以得到
dx=Sum[l,r] xor dl1 xor dr
l1,r,就判断
dl1 xor dr的奇偶性判断是否有解即可
Ml,rl,rmaphash

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#define modn 20011
#define N 100005

using namespace std;

map <int, int> Map;

struct Node {
    int l, r, w;
}a[N];
int Hash[modn][2], f[N], d[N], n, m, cnt;

int Getid(int x) {
    int k = x % modn;
    while (Hash[k][0] && Hash[k][0] != x) {
        k++;
        if (k = modn) k = 0;
    }
    if (!Hash[k][0]) Hash[k][1] = ++cnt;
    Hash[k][0] = x;
    return k;
}

int Find(int x) {   
    if (f[x] == x) return x;
    int rp = Find(f[x]);
    d[x] = d[x] ^ d[f[x]];
    return f[x] = rp;
}

int main() {
    scanf("%d %d", &n, &m);
    for (int i = 0; i < modn; i++) f[i] = i, d[i] = 0;
    for (int i = 1; i <= m; i++) {
         char str[5];
         scanf("%d %d %s", &a[i].l, &a[i].r, str);
         a[i].l--;
         if (str[0] == 'e') a[i].w = 0;
                       else a[i].w = 1;
         Getid(a[i].l);
         Getid(a[i].r);
    }
    for (int i = 1; i <= m; i++) {
         int idx = Getid(a[i].l);
         int idy = Getid(a[i].r);
         int p = Find(idx);
         int q = Find(idy);
         if (p == q) {
             if (d[idx] ^ d[idy] != a[i].w) {
                 printf("%d\n", i - 1);
                 return 0;
             }
         } else f[p] = q, d[p] = d[idx] ^ d[idy] ^ a[i].w;
    }
    printf("%d\n", m);
    return 0;
}
阅读更多 登录后自动展开
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页