poj1733(区间上的种类并查集)
题目大意是:一个由0,1组成的数字串~~,现在你问一个人,第i位到第j位的1的个数为奇数还是偶数。一共会告诉你几组这样的数
要你判断前k组这个人回答的都是正确的,到第k+1组,这个人说的是错的,要你输出这个k,要是这个人回答的都是正确的,则输出组数
odd为奇数,even为偶数。
Sample Input
10 5 1 2 even 3 4 odd 5 6 even 1 6 even 7 10 odd
Sample Output
3
思路:赤裸裸的种类并查集吧.......其中,我们把一段区间为奇数标记为0,为偶数标记为1,然后如果区间连贯,也就是说区间1到区间2,区间3到区间4,那么就是可以连贯成区间1到区间4的,如此的话,可以是左极限-1,或者右极限+1......判断是否在同一个树上,在的话,判断是否正确,不在的话,连接起来,在连接的时候,按照种类并查集的操作即可.......
ac代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int father[50005],rank[50005],ans=0; struct node { int v1,v2; char ch[10]; int num; } s[50005]; int t[50005],flag; int cmp(const node a,const node b) { if(a.num<b.num) return 1; else return 0; } int find(int x) { if(x==father[x]) return x; int tmp=father[x]; father[x]=find(tmp); rank[x]=(rank[x]+rank[tmp])%2; return father[x]; } void liantong(int x,int y,int k) { int xx=find(x); int yy=find(y); if(xx==yy) { int sum=(2-rank[x]+rank[y])%2; if(sum!=k) flag=0; // return; } if(xx>yy) { father[xx]=yy; rank[xx]=(2-k+2-rank[x]+rank[y])%2; } if(xx<yy) { father[yy]=xx; rank[yy]=(2-k+2-rank[y]+rank[x])%2; } //printf("%d %d %d %d %d\n",x,y,rank[x],rank[y],k); } int erfen(int ll,int rr,int k) { while(ll<=rr) { int mid=(ll+rr)/2; if(t[mid]>k) rr=mid-1; else ll=mid+1; } return rr; } int main() { int n,m; while(scanf("%d",&n)>0) { if(n==-1) break; scanf("%d",&m); for(int i=0; i<=20005; i++) { father[i]=i; rank[i]=0; } /*if(m==0) { printf("0\n"); return 0; }*/ int cnt=0; for(int i=0; i<m; i++) { s[i].num=i; scanf("%d%d%s",&s[i].v1,&s[i].v2,s[i].ch); t[cnt++]=s[i].v1; t[cnt++]=s[i].v2; } sort(t,t+cnt); int cnt1=1; for(int i=1; i<cnt; i++) if(t[i]!=t[i-1]) t[cnt1++]=t[i]; for(int i=cnt1-1; i>0; i--) if(t[i]!=t[i-1]+1) t[cnt1++]=t[i-1]+1; sort(t,t+cnt1); for(int i=cnt1; i>0; i--) t[i]=t[i-1]; //for(int i=1; i<=cnt1; i++) // printf("%d\t",t[i]); int ans=m; flag=1; for(int i=0; i<m; i++) { int x=erfen(1,cnt1,s[i].v1); int y=erfen(1,cnt1,s[i].v2); if(s[i].ch[0]=='e') liantong(x-1,y,0); else liantong(x-1,y,1); if(flag==0) { ans=i; break; } } //for(int i=0;i<=n;i++) //printf("%d\n",rank[i]); printf("%d\n",ans); } return 0; } /* 3 3 1 2 odd 2 3 odd 1 3 even */
朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。