题意:题目:有一个长度 已知的01串,给出多个条件,[l,r]这个区间中1的个数是奇数还是偶数,问前几个是正确的,没有矛盾
链接:点我
解题思路:hash离散化+并查集
首先我们不考虑离散化:s[x]表示(root[x],x]区间1的个数的奇偶性,0-偶数,1-奇数
每个输入区间[a,b],首先判断a-1与b的根节点是否相同
a)如果相同表示(a-1,b]之间1的个数奇偶性已知s((a-1,b])=s[a-1]^s[b],此时只需简单判断即可
b)如果不同,我们需要合并两个子树,我们将root较大的子树(例root[a])合并到root较小的子树(例root[b]),且此时s[root[a]]=s[a]^s[b]^s((a-1,b])
在路径压缩的过程中s[i]=s[i]^s[root[i]],s[root[i]]为(root[root[i]], root[i]]区间内1个数的奇偶性,例(a, b]区间1的个数为偶数,(b, c]区间1的个数为奇数,(a, c]之间1的个数显然为0^1=1奇数
1 /* 2 POJ 1733 3 HASH+并查集实现 4 */ 5 #include <stdio.h> 6 #include <algorithm> 7 #include <iostream> 8 #include <string.h> 9 using namespace std; 10 11 const int HASH=10007; 12 const int MAXN=10010; 13 14 struct HASHMAP 15 { 16 int head[HASH]; 17 int next[MAXN]; 18 int size; 19 int state[MAXN]; 20 void init() 21 { 22 size=0; 23 memset(head,-1,sizeof(head)); 24 } 25 int push(int st) 26 { 27 int i,h=st%HASH; 28 for(i=head[h];i!=-1;i=next[i]) 29 if(state[i]==st) 30 return i; 31 state[size]=st; 32 next[size]=head[h]; 33 head[h]=size++; 34 return size-1; 35 } 36 }hm; 37 int F[MAXN]; 38 int val[MAXN]; 39 int find(int x) 40 { 41 if(F[x]==-1)return x; 42 int tmp=find(F[x]); 43 val[x]^=val[F[x]]; 44 return F[x]=tmp; 45 } 46 47 int main() 48 { 49 int n,m; 50 int u,v; 51 char str[20]; 52 while(scanf("%d%d",&n,&m)==2) 53 { 54 hm.init(); 55 memset(F,-1,sizeof(F)); 56 memset(val,0,sizeof(val)); 57 int ans=m; 58 for(int i=0;i<m;i++) 59 { 60 scanf("%d%d%s",&u,&v,&str); 61 if(u>v)swap(u,v); 62 if(ans<m)continue; 63 64 u=hm.push(u-1); 65 v=hm.push(v); 66 //printf("%d %d\n",u,v); 67 68 int tmp; 69 if(str[0]=='e')tmp=0; 70 else tmp=1; 71 int t1=find(u); 72 int t2=find(v); 73 74 if(t1==t2) 75 { 76 if(val[u]^val[v]!=tmp)ans=i; 77 } 78 else 79 { 80 F[t2]=t1; 81 val[t2]=tmp^val[u]^val[v]; 82 } 83 84 } 85 printf("%d\n",ans); 86 } 87 return 0; 88 }