题目大意:
给出M个区间的描述Li,Ri,str,当str为even时,表示区间[Li,Ri]有偶数个1,否则有奇数个1,题目会给出区间的最大长度N。 给 出 M 个 区 间 的 描 述 L i , R i , s t r , 当 s t r 为 e v e n 时 , 表 示 区 间 [ L i , R i ] 有 偶 数 个 1 , 否 则 有 奇 数 个 1 , 题 目 会 给 出 区 间 的 最 大 长 度 N 。
N≤109
N
≤
10
9
M≤104
M
≤
10
4
分析:
首先我们可以想到,
首
先
我
们
可
以
想
到
,
①奇-偶=奇
②奇-奇=偶
③偶-偶=偶
所以,当
区间
[L,R]内的1
[
L
,
R
]
内
的
1
,即
Sum[l,r]
S
u
m
[
l
,
r
]
有偶数个,
那么显然
因为Sum[l,r]=Sum[1,r]−Sum[1,l−1]
因
为
S
u
m
[
l
,
r
]
=
S
u
m
[
1
,
r
]
−
S
u
m
[
1
,
l
−
1
]
所以
Sum[1,r]和Sum[1,l−1]
S
u
m
[
1
,
r
]
和
S
u
m
[
1
,
l
−
1
]
的奇偶性相同
同理
Sum[l,r]
S
u
m
[
l
,
r
]
有奇数个,
那么
Sum[1,r]和Sum[1,l−1]
S
u
m
[
1
,
r
]
和
S
u
m
[
1
,
l
−
1
]
的奇偶性不同
那么我们可以考虑用带权并查集去做,
当
d[x]=0时表示x与其father奇偶性相同
d
[
x
]
=
0
时
表
示
x
与
其
f
a
t
h
e
r
奇
偶
性
相
同
当
d[x]=1时则表示x与其father奇偶性不同
d
[
x
]
=
1
时
则
表
示
x
与
其
f
a
t
h
e
r
奇
偶
性
不
同
那么可以通过
xor
x
o
r
运算求出
x
x
与当前集合的树根奇偶性
对于一个区间
[l,r]以及他们的Sum[l,r]
[
l
,
r
]
以
及
他
们
的
S
u
m
[
l
,
r
]
,
我们显然可以发现,当
l−1与r不在同一个集合中的时候,就可以连边
l
−
1
与
r
不
在
同
一
个
集
合
中
的
时
候
,
就
可
以
连
边
设点l−1的集合的树根为x,r的集合的树根为y,
设
点
l
−
1
的
集
合
的
树
根
为
x
,
r
的
集
合
的
树
根
为
y
,
然后
x向y
x
向
y
连边即可
可是这时候的
d[x]该怎么求呢?
d
[
x
]
该
怎
么
求
呢
?
我们已经知道
我
们
已
经
知
道
l−1到r的奇偶性Sum[l,r]
l
−
1
到
r
的
奇
偶
性
S
u
m
[
l
,
r
]
l−1到x的奇偶性dl−1
l
−
1
到
x
的
奇
偶
性
d
l
−
1
r到y的奇偶性dr
r
到
y
的
奇
偶
性
d
r
那么显然可以得到
dx=Sum[l,r]
d
x
=
S
u
m
[
l
,
r
]
xor
dl−1
d
l
−
1
xor
dr
d
r
当
l−1,r在同一个集合的时候
l
−
1
,
r
在
同
一
个
集
合
的
时
候
,就判断
dl−1
d
l
−
1
xor
dr
d
r
的奇偶性判断是否有解即可
因为M很小而l,r很大,所以我们可以对l,r进行map或者hash
因
为
M
很
小
而
l
,
r
很
大
,
所
以
我
们
可
以
对
l
,
r
进
行
m
a
p
或
者
h
a
s
h
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#define modn 20011
#define N 100005
using namespace std;
map <int, int> Map;
struct Node {
int l, r, w;
}a[N];
int Hash[modn][2], f[N], d[N], n, m, cnt;
int Getid(int x) {
int k = x % modn;
while (Hash[k][0] && Hash[k][0] != x) {
k++;
if (k = modn) k = 0;
}
if (!Hash[k][0]) Hash[k][1] = ++cnt;
Hash[k][0] = x;
return k;
}
int Find(int x) {
if (f[x] == x) return x;
int rp = Find(f[x]);
d[x] = d[x] ^ d[f[x]];
return f[x] = rp;
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 0; i < modn; i++) f[i] = i, d[i] = 0;
for (int i = 1; i <= m; i++) {
char str[5];
scanf("%d %d %s", &a[i].l, &a[i].r, str);
a[i].l--;
if (str[0] == 'e') a[i].w = 0;
else a[i].w = 1;
Getid(a[i].l);
Getid(a[i].r);
}
for (int i = 1; i <= m; i++) {
int idx = Getid(a[i].l);
int idy = Getid(a[i].r);
int p = Find(idx);
int q = Find(idy);
if (p == q) {
if (d[idx] ^ d[idy] != a[i].w) {
printf("%d\n", i - 1);
return 0;
}
} else f[p] = q, d[p] = d[idx] ^ d[idy] ^ a[i].w;
}
printf("%d\n", m);
return 0;
}