题意:有一个长度已知的01串,给出[l,r]这个区间中的1是奇数个还是偶数个,给出一系列语句问前几个是正确的
思路:如果我们知道[1,2][3,4][5,6]区间的信息,我们可以求出[1,6]的信息
可以将将闭区间[x,y]转换成(x - 1,y]左开右闭区间
那么我们可以用并查集来做,每次输入两个数 x 和 y 判断两者是否在同一并查集中,如果在,那么可以直接判断奇偶
如果两者不在同一并查集中将两者合并,并求出两者的根之间的距离
距离可在 find 函数中维护
注意:数据范围比较大,需要离散化
——代码

1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #define N 1000001 5 6 int n, m, cnt, ans; 7 int a[N], b[N], q[N << 1], f[N << 1], d[N << 1]; 8 char s[N][10]; 9 10 inline int read() 11 { 12 int x = 0, f = 1; 13 char ch = getchar(); 14 for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1; 15 for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0'; 16 return x * f; 17 } 18 19 inline int find(int x) 20 { 21 if(x ^ f[x]) 22 { 23 int fx = f[x]; 24 f[x] = find(f[x]); 25 d[x] = d[x] ^ d[fx]; 26 } 27 return f[x]; 28 } 29 30 int main() 31 { 32 int i, x, y, fx, fy; 33 while(scanf("%d", &n) != EOF) 34 { 35 m = read(); 36 ans = cnt = 0; 37 for(i = 1; i <= m; i++) 38 { 39 a[i] = read() - 1; 40 b[i] = read(); 41 scanf("%s", s[i]); 42 q[++cnt] = a[i]; 43 q[++cnt] = b[i]; 44 } 45 std::sort(q + 1, q + cnt + 1); 46 cnt = std::unique(q + 1, q + cnt + 1) - q - 1; 47 for(i = 1; i <= cnt; i++) f[i] = i, d[i] = 0; 48 for(i = 1; i <= m; i++) 49 { 50 x = std::lower_bound(q + 1, q + cnt + 1, a[i]) - q; 51 y = std::lower_bound(q + 1, q + cnt + 1, b[i]) - q; 52 fx = find(x); 53 fy = find(y); 54 if(fx == fy) 55 { 56 if((d[x] == d[y]) == (s[i][0] == 'o')) break; 57 } 58 else 59 { 60 f[fx] = fy; 61 d[fx] = d[x] ^ d[y] ^ (s[i][0] == 'o'); 62 } 63 ans++; 64 } 65 printf("%d ", ans); 66 } 67 return 0; 68 }