题意:有一个长度已知的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;
}