题目链接: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; }