题目传送门
题目大意
有一个很长很长的01串(你不知道是什么)。有$n$条线索,每条线索是01串上的一段的1的个数的奇偶性。求最小的$X$,使得存在一个串满足前$X$条线索,但不存在串满足前$X + 1$条线索或者输出$n$表示存在一个串满足所有线索。
将区间求和变成前缀和相减,这样每条线索等价于告诉你两个位置的前缀和奇偶性是否相同。
直接上带权并查集维护。对于每条线索如果涉及的两个位置没有连通就连通,否则判断是否合法。
Code
1 /** 2 * poj 3 * Problem#1733 4 * Accepted 5 * Time: 32ms 6 * Memory: 816k 7 */ 8 #include <algorithm> 9 #include <iostream> 10 #include <cstdlib> 11 #include <cstdio> 12 using namespace std; 13 typedef bool boolean; 14 15 const int N = 5e3 + 5; 16 17 int L, n; 18 char str[10]; 19 pair<int, int> ps[N]; 20 boolean relation[N]; 21 int buf[N << 1]; 22 int uf[N << 1], mask[N << 1]; 23 24 inline void init() { 25 scanf("%d%d", &L, &n); 26 for (int i = 1; i <= n; i++) { 27 scanf("%d%d%s", &ps[i].first, &ps[i].second, str); 28 ps[i].first--; 29 relation[i] = (str[0] == 'o'); 30 buf[(i << 1) - 1] = ps[i].first, buf[(i << 1)] = ps[i].second; 31 } 32 } 33 34 void discrete() { 35 sort(buf + 1, buf + (n << 1) + 1); 36 for (int i = 1; i <= n; i++) { 37 ps[i].first = lower_bound(buf + 1, buf + (n << 1) + 1, ps[i].first) - buf; 38 ps[i].second = lower_bound(buf + 1, buf + (n << 1) + 1, ps[i].second) - buf; 39 } 40 } 41 42 int find(int x) { 43 if (uf[x] == x) 44 return x; 45 int lastfather = uf[x]; 46 uf[x] = find(uf[x]); 47 mask[x] ^= mask[lastfather]; 48 return uf[x]; 49 } 50 51 inline void solve() { 52 int doublen = n << 1; 53 for (int i = 1; i <= doublen; i++) 54 uf[i] = i, mask[i] = 0; 55 for (int i = 1; i <= n; i++) { 56 if (find(ps[i].first) == find(ps[i].second)) { 57 int val1 = mask[ps[i].first], val2 = mask[ps[i].second]; 58 if ((val1 ^ val2) != relation[i]) { 59 printf("%d ", i - 1); 60 return; 61 } 62 } else { 63 int ffather = find(ps[i].first); 64 mask[ffather] = relation[i] ^ mask[ps[i].first]; 65 uf[ffather] = ps[i].second; 66 } 67 } 68 printf("%d ", n); 69 } 70 71 int main() { 72 init(); 73 discrete(); 74 solve(); 75 return 0; 76 }