题意:
一个长度为
N
N
N 的由
0
0
0 和
1
1
1 组成的序列
S
S
S。
M
M
M 个询问,返回
[
l
,
r
]
[l,r]
[l,r] 中
1
1
1 的个数是奇数还是偶数。输出一个最小的
k
k
k,使得存在一个
01
01
01 序列满足第
1
k
−
1
1~k-1
1 k−1 个回答,但不存在满足第
1
k
1~k
1 k 个回答的
01
01
01 序列。
(
N
≤
1
0
9
,
M
≤
10000
)
(N\leq 10^9,M\leq 10000)
(N≤109,M≤10000)
思路:
N N N 比较大,但是询问比较少,因此需要将所有数字离散化。
然后我们需要处理区间 [ l , r ] [l,r] [l,r] 的 1 1 1 的个数是偶数还是奇数。因此我们来定义一下 x → r o o t x\rightarrow root x→root, d [ x ] d[x] d[x] 表示 s u m [ r o o t ] − s u m [ x ] sum[root]-sum[x] sum[root]−sum[x] 的值为奇数还是偶数,即 [ x + 1 , r o o t ] [x+1,root] [x+1,root] 中 1 1 1 的个数为奇数还是偶数。如果维护的是 [ x , r o o t ] [x,root] [x,root] 的信息,那么 d [ x ] d[x] d[x] 初始值就不确定了,因此维护的是 [ x + 1 , r o o t ] [x+1,root] [x+1,root], d [ x ] d[x] d[x] 初始为 0 0 0 。
所以 x → r o o t x\rightarrow root x→root 为 0 0 0,表示 [ x + 1 , r o o t ] [x+1,root] [x+1,root] 中 1 1 1 的个数为偶数。如果为 1 1 1,则表示 1 1 1 的个数为奇数。在合并时维护一个模 2 2 2 剩余系。
比如 [ x , y ] [x,y] [x,y] 中 1 1 1 的个数为偶数,则 ( x − 1 ) → y (x-1)\rightarrow y (x−1)→y 为 0 0 0, f a [ f x ] = f y , d [ f x ] = ( x → y ) − ( x → f x ) − ( f y → y ) = ( 0 − d [ x ] + d [ y ] + 2 ) m o d 2 fa[fx] = fy,d[fx] = (x\rightarrow y)-(x\rightarrow fx)-(fy\rightarrow y)=(0-d[x]+d[y]+2)\ mod\ 2 fa[fx]=fy,d[fx]=(x→y)−(x→fx)−(fy→y)=(0−d[x]+d[y]+2) mod 2。
查询 [ x , y ] [x,y] [x,y] 中 1 1 1 个数奇偶,直接 ( d [ x ] − d [ y ] + 2 ) m o d 2 (d[x]-d[y]+2)\ mod \ 2 (d[x]−d[y]+2) mod 2,为 0 0 0 则为偶,否则为奇。
至此即可完成本题。
ps:本题也可以维护并查集路径上节点的异或和, 0 0 0 表示为偶, 1 1 1 表示为奇。
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define LOG1(x1,x2) cout << x1 << ": " << x2 << endl;
#define LOG2(x1,x2,y1,y2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << endl;
typedef long long ll;
typedef double db;
const db EPS = 1e-9;
using namespace std;
const int N = 2*1e4+100;
int n,m,fa[N],d[N],a[N],tot;
struct Query{
int x,y,op;
}q[N];
int find(int x){
if(x == fa[x]) return x;
int root = find(fa[x]);
d[x] = (d[x]+d[fa[x]]+2)%2;
return fa[x] = root;
}
int search_for(int x){
return lower_bound(a+1,a+1+tot,x)-a;
}
int main()
{
scanf("%d%d",&n,&m); tot = 0;
rep(i,1,m){
scanf("%d%d",&q[i].x,&q[i].y);
char oop[10]; scanf("%s",oop);
if(oop[0] == 'e') q[i].op = 1; //偶数
else q[i].op = 0; //奇数
a[++tot] = q[i].x-1, a[++tot] = q[i].y;
}
sort(a+1,a+1+tot);
tot = unique(a+1,a+1+tot)-a-1;
rep(i,0,tot) fa[i] = i, d[i] = 0;
int ans = m;
rep(i,1,m){
int xx = search_for(q[i].x-1), yy = search_for(q[i].y), cc = q[i].op;
int fx = find(xx), fy = find(yy);
if(cc){ //偶数
if(fx != fy){
fa[fx] = fy;
d[fx] = (d[yy]-d[xx]+2)%2;
}
else{
int jud = (d[xx]-d[yy]+2)%2;
if(jud == 1){
ans = i-1;
break;
}
}
}
else { //奇数
if(fx != fy){
fa[fx] = fy;
d[fx] = (d[yy]-d[xx]+2+1)%2;
}
else{
int jud = (d[xx]-d[yy]+2)%2;
if(jud == 0){
ans = i-1;
break;
}
}
}
}
printf("%d\n",ans);
return 0;
}