poj1733 parity game---离散化+带权并查集
题目链接:https://vjudge.net/problem/POJ-1733
题意:给定一个01序列,对于每个给出的区间,回答一个区间内1的个数为奇数还是偶数。求在第几条回答时出现矛盾
设v[x]=0/1表示x与par[x]组成的区间有偶数/奇数个1,之后利用异或的性质使用带权并查集即可,具体就是加减的奇偶性和异或相对应(由此可发现只能设v[x]=0表示偶数)。序列可能很长,但是询问只有5000个,所以需要离散化,这儿偷懒用了map。另外还有一个小技巧之前用过,就是将左边区间变成开区间,这个在hdu3038中也用到了
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
const int maxn=10000;
int t,n,q,i,cnt,f,ans;
int par[maxn+10],v[maxn+10];
map<int,int> c;
int find(int x){
if (par[x]!=x){
int u=par[x];
par[x]=find(par[x]);
v[x]^=v[u]; //*
}
return par[x];
}
int main(){
std::ios::sync_with_stdio(false);
cin>>n>>q; f=0;
for (i=1;i<=maxn;i++) par[i]=i;
for (i=1;i<=q;i++){
int a,b; string s;
cin>>a>>b; cin>>s;
if (a>b) swap(a,b); //*
if (c[a-1]==0) c[a-1]=(++cnt); if (c[b]==0) c[b]=(++cnt); //离散化
int fa=find(c[a-1]); int fb=find(c[b]);
if (fa==fb){
int t=v[c[a-1]]^v[c[b]]; //*
if (((t==0&&s=="odd")||(t==1&&s=="even"))&&f==0) {
f=1; ans=i-1;
}
}
else{
int t=(s=="odd")?1:0;
par[fa]=fb; v[fa]=t^v[c[a-1]]^v[c[b]]; //*
}
}
if (f==0) cout<<q<<endl; else cout<<ans<<endl;
return 0;
}

浙公网安备 33010602011771号