奇偶游戏
奇偶游戏
题意:
小 A和小 B 在玩一个游戏。
首先,小 A写了一个由 0 和 1组成的序列 S,长度为 N。
然后,小 B 向小 A 提出了 M 个问题。
在每个问题中,小 B 指定两个数 l 和 r,小 A 回答 S[l∼r]中有奇数个 1还是偶数个 1。
机智的小 B 发现小 A 有可能在撒谎。
例如,小 A 曾经回答过 S[1∼3] 中有奇数个 1,S[4∼6] 中有偶数个 1,现在又回答 S[1∼6]中有偶数个 1,显然这是自相矛盾的。
请你帮助小 B 检查这 M个答案,并指出在至少多少个回答之后可以确定小 A一定在撒谎。
即求出一个最小的 kk,使得 01 序列 S 满足第 1∼k 个回答,但不满足第 1∼k+1个回答。
思路:
前缀和+异或性质+并查集+离散化
我们可以用d数组表示序列S的前缀和,那么会得到以下性质.
d[l~r]有偶数个1,等价于d[l-1]与d[r]奇偶性相同 (1+0=1 0+0=0,1是奇数,0是偶数)
d[l~r]有奇数个1,等价于d[l-1]与d[r]奇偶性不同 (1+1=0 0+1=0,1是奇数,0是偶数
以下是传递关系细目表
如果说x1和x2奇偶性质相同,x2与x3奇偶性质相同,那么x1和x3也相同
如果说x1和x2奇偶性质相同,x2与x3奇偶性质不同,那么x1和x3也不同
如果说x1和x2奇偶性质不同,x2与x3奇偶性质不同,那么x1和x3就相同
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e4+10;
int f[N],d[N],cnt;
int n;
unordered_map<int,int>mp;
int find(int x){
if(x!=f[x]){
int root=find(f[x]);
d[x]^=d[f[x]];
x=root;
}
return f[x];
}
int get(int x){//离散化
if(mp.count(x)==0){
mp[x]=++cnt;
}
return mp[x];
}
signed main(){
cin>>n;
int m;
cin>>m;
int flag=1;
for(int i=1;i<N;i++){
f[i]=i;
}
for(int i=1;i<=m;i++){
string s;
int l,r;
cin>>l>>r>>s;
if(flag==0) continue;
l--;
l=get(l);
r=get(r);
int cha=0;
if(s=="odd"){
cha=1;
}
int fa=find(l);
int fb=find(r);
if(fa!=fb){
f[fa]=fb;
d[fa]=d[l]^d[r]^cha;
}
else{
if(d[l]^d[r]!=cha){
cout<<i-1<<endl;
flag=0;
}
}
}
if(flag) cout<<m<<endl;
}

浙公网安备 33010602011771号