ural 1003 Parity

有一个长度为$n$的$01$序列,有$k$组已公开情报,第$i$组为下标在$[l_i,r_i]$的元素的和的奇偶性为$o_i$

问第一个有冲突的情报是哪个

如果都没有冲突,输出$k$

十分巧妙的带权并查集

先对序列做前缀异或和,这样情报就转化为了$s_r \oplus s_{l-1}=o$

也就是说$s_r$和$s_{l-1}$的距离为$o$,用带权并查集维护一下就行了

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e5 + 10;
 4 map<int, int> id; int tot;
 5 int n, m;
 6 struct T { int l, r, o; } t[N];
 7 
 8 int fa[N], dis[N];
 9 
10 int get(int x) {
11     if(x == fa[x]) return x;
12     int f = get(fa[x]);
13     dis[x] ^= dis[fa[x]];
14     return fa[x] = f;
15 }
16 
17 int merge(int x, int y, int o) {
18     int fx = get(x), fy = get(y);
19     if(fx == fy) return dis[x] ^ dis[y] == o;
20     fa[fx] = fy;
21     dis[fx] = dis[x] ^ dis[y] ^ o;
22     return 1;
23 }
24 
25 void sol() {
26     tot = 0, id.clear();
27     scanf("%d", &m);
28     for(int i = 1 ; i <= m ; ++ i) {
29         char s[10]; int l, r;
30         scanf("%d%d%s", &l, &r, s);
31         if(id[r] == 0) id[r] = ++ tot;
32         if(id[l - 1] == 0) id[l - 1] = ++ tot;
33         t[i] = (T) { id[l - 1], id[r], s[0] == 'o' };
34     }
35     for(int i = 1 ; i <= tot ; ++ i) fa[i] = i, dis[i] = 0;
36     for(int i = 1 ; i <= m ; ++ i) {
37         int x = t[i].l, y = t[i].r, o = t[i].o;
38         if(!merge(x, y, o)) {
39             printf("%d\n", i - 1);
40             return ;
41         }
42     }
43     printf("%d\n", m);
44 }
45 
46 int main() {
47     while(scanf("%d", &n) == 1 && n != -1) sol();
48 }
ural 1003 Parity
posted @ 2018-09-02 16:34  KingSann  阅读(153)  评论(0编辑  收藏  举报