题意:有一个长度已知的01串,给出[l,r]这个区间中的1是奇数个还是偶数个,给出一系列语句问前几个是正确的
一类经典的并查集题目,经典模型就是将[l,r]这个区间化为(l-1,r],那么1的个数就可以表示为sum[r]-sum[l-1],也就确定了奇偶性,我们可以用r[]数组表示这个端点到它的根节点的1的奇偶(这个区间就是(i,root(i)](0代表偶,1代表奇) 对于每个输入的区间,我们查找它们的根节点是否相同。
1.如果相同,证明这个区间的奇偶性在之前已经得知,那么直接判断即可。
2.如果不同,那么就是u-1与v此时不在同一个集合中,那么我们可以知道(u-1,root([u-1])]区间和(v,root([v])]区间1的奇偶,并且我们知道了(u-1,v]区间1的奇偶,那么就可以推算出(root([u-1]),root([v])]区间的属性,进而合并两者。在合并时,根节点,r[root(u)]=r(u)^r(v)^r(u-1,v], 在路径压缩过程中r[i]=r[i]^r[root(i)],比如(a,b]中1的个数为偶数,(b,c]中1的个数为奇数,(a,c]中1的个数显然为奇数
数据范围1e9,很大,语句5000条,所以需要把数据离散化
学习了一下离散化https://blog.csdn.net/xiangaccepted/article/details/73276826
const int maxn=1e5+10; int a[maxn], t[maxn]; int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",a[i]),t[i]=a[i]; sort(t+1,t+n+1); m=unique(t+1,t+1+n)-t-1;//m为不重复的元素的个数 for(int i=1;i<=n;i++) a[i]=lower_bound(t+1,t+1+m,a[i])-t; //原来的a[i]离散化后成了后来的a[i]; //离散化后的a[i]范围是(1-m);
链接:poj 1733
#include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<string> #include <cmath> #include <map> #include <stack> using namespace std; const int maxn = 10000 + 10; const int inf = 0x3f3f3f3f; int n, m; int father[maxn]; int r[maxn]; int que[maxn]; int cnt; struct node { int u, v; int res; }a[maxn]; int getf(int x) { if(x != father[x]) { int t = father[x]; father[x] = getf(father[x]); r[x] = r[x] ^ r[t]; } return father[x]; } int main() { int T; while(cin >> n) { cin >> m; char str[10]; cnt = 0; for(int i = 0; i < m; i++) { scanf("%d %d %s", &a[i].u, &a[i].v, str); a[i].u--; if(str[0] == 'e') { a[i].res = 1; } else { a[i].res = 0; } que[cnt++] = a[i].u; que[cnt++] = a[i].v; } sort(que, que + cnt); int ans = unique(que, que + cnt) - que; for(int i = 0; i < ans; i++) { father[i] = i; r[i] = 0; } int sum = 0; for(int i = 0; i < m; i++) { int u = lower_bound(que, que + ans, a[i].u) - que; int v = lower_bound(que, que + ans, a[i].v) - que; int ra = getf(u); int rb = getf(v); if(ra == rb) { if(r[u] == r[v] && a[i].res == 0) { break; } if(r[u] != r[v] && a[i].res == 1) { break; } sum++; } else { if(a[i].res == 0) { father[ra] = rb; r[ra] = r[u] ^ r[v] ^ 1; } else { father[ra] = rb; r[ra] = r[u] ^ r[v]; } sum++; } } cout << sum << endl; } return 0; }