并查集
首先将 sum[l, r] 的奇偶性转换成 sum[1, l - 1] 和 sum[1, r] 的奇偶性是否相同
注意是 l - 1
然后维护并查集,有边带权和扩展域两种做法
边带权
若两数奇偶性相同,边权为 0 ,若不同,边权为 1 ,然后异或处理即可
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int MAXN = 20005;
int n, m, fa[MAXN], dis[MAXN], dat[MAXN], sub[MAXN], id[MAXN], tot;
struct po{
int u, v, opt;
}a[MAXN];
char s[10];
int find(int x) {
if(x != fa[x]) {
int t = find(fa[x]);
dis[x] ^= dis[fa[x]];
fa[x] = t;
return fa[x];
}
return fa[x];
}
int main() {
cin >> m >> n;
for(int i = 1; i <= n; i++) {
cin >> a[i].u >> a[i].v >> s;
if(s[0] == 'o') a[i].opt = 1;
else a[i].opt = 0;
++tot, sub[tot] = dat[tot] = a[i].u;
++tot, sub[tot] = dat[tot] = a[i].v;
}
sort(sub + 1, sub + 1 + tot);
tot = unique(sub + 1, sub + 1 + tot) - sub - 1;
for(int i = 1; i <= n * 2; i++) {
id[i] = lower_bound(sub + 1, sub + 1 + tot, dat[i]) - sub;
}
//for(int i = 1; i <= n * 2; i++) printf("%d %d
", dat[i], id[i]);
for(int i = 1; i <= tot; i++) fa[i] = i;
for(int i = 1; i <= n; i++) {
a[i].u = id[i * 2 - 1] - 1, a[i].v = id[i * 2];
int r1 = find(a[i].u), r2 = find(a[i].v);
//printf("%d %d
", a[i].u, a[i].v);
if(r1 != r2) {
fa[r1] = r2;
dis[r1] = a[i].opt ^ dis[a[i].u] ^ dis[a[i].v];
}else {
if((dis[a[i].u] ^ dis[a[i].v]) != a[i].opt) {printf("%d
", i - 1);return 0;}
}
}
/*for(int i = 1; i <= tot; i++) {
printf("%d %d %d
",i + 1, fa[i], dis[i]);
}*/
printf("%d
", n);
return 0;
}
扩展域
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int MAXN = 20005;
int n, m, fa[MAXN], dat[MAXN], sub[MAXN], id[MAXN], tot;
struct po{
int u, v, opt;
}a[MAXN];
char s[10];
int find(int x) {
if(x != fa[x]) return fa[x] = find(fa[x]);
return fa[x];
}
void merge(int x, int y) {
int r1 = find(x), r2 = find(y);
if(r1 != r2){
fa[r1] = r2;
}
}
int main() {
cin >> m >> n;
for(int i = 1; i <= n; i++) {
cin >> a[i].u >> a[i].v >> s;
if(s[0] == 'o') a[i].opt = 1;
else a[i].opt = 0;
++tot, sub[tot] = dat[tot] = a[i].u;
++tot, sub[tot] = dat[tot] = a[i].v;
}
sort(sub + 1, sub + 1 + tot);
tot = unique(sub + 1, sub + 1 + tot) - sub - 1;
for(int i = 1; i <= n * 2; i++) {
id[i] = lower_bound(sub + 1, sub + 1 + tot, dat[i]) - sub;
}
tot++;
//for(int i = 1; i <= n * 2; i++) printf("%d %d
", dat[i], id[i]);
for(int i = 1; i <= tot * 2; i++) fa[i] = i;
for(int i = 1; i <= n; i++) {
a[i].u = id[i * 2 - 1] - 1, a[i].v = id[i * 2];
int u = a[i].u, v = a[i].v;
if(a[i].opt) {
if(find(u) == find(v)) {printf("%d
", i - 1); return 0;}
merge(u, v + tot);merge(v, u + tot);
}else {
if(find(u) == find(v + tot) || find(v) == find(u + tot)) {printf("%d
", i - 1);return 0;}
merge(u, v);merge(u + tot, v + tot);
}
}
/*for(int i = 1; i <= tot; i++) {
printf("%d %d %d
",i + 1, fa[i], dis[i]);
}*/
printf("%d
", n);
return 0;
}