题意:一个由0,1组成的数字串,现在你问一个人,第i位到第j位的1的个数为奇数还是偶数。一共会告诉你n组这样的数。要你判断前k组这个人回答的都是正确的,到第k+1组,这个人说的是错的,要你输出这个k,要是这个人回答的都是正确的,则输出组数。
思路:并查集。注意输入的区间非常大,所以要离散化一下。离散化的时候还要注意,如果两个数字相邻但是其差不为1,那么中间必须再加上另一个数。比如将出现的数字排序后连续的两个数字是3和8,那么中间必须加上一个数字(4~7都行)。这是为了防止这样的情况:3~3和8~8都是奇数,3~8也是奇数。如果中间不加数,离散化之后就会判断为错,实际上这是可能的。
接着就是并查集的过程,与找同性恋虫子那题类似。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define clr(s,t) memset(s,t,sizeof(s)) #define N 15005 struct node{ int x,y,flag; }p[N]; int s[N<<1],t[N<<1],f[N],parity[N]; int T,n; int find(int x){ int tmp = f[x]; if(f[x] == x) return x; f[x] = find(f[x]); parity[x] = (parity[tmp]+parity[x])&1; return f[x]; } int main(){ int i,j,a,b,xx,yy,len,top; char str[10]; clr(parity, 0); scanf("%d",&T); scanf("%d",&n); if(!n){ printf("0\n"); return 0; } len = 0; for(i = 1;i<=n;i++){ scanf("%d %d %s",&p[i].x,&p[i].y,str); s[len++] = p[i].x; s[len++] = p[i].y; p[i].flag = (str[0]=='o'); } sort(s,s+len); top = 0; t[top++] = s[0]; for(i = 1;i<len;i++){ if(s[i] - s[i-1] > 1)//中间差一个数至关重要 t[top++] = s[i-1]+1; t[top++] = s[i]; } memcpy(s, t, sizeof(s)); len = top; len = (int)(unique(s, s+len) - s); for(i = 0;i<=len;i++) f[i] = i; for(i = 1;i<=n;i++){ a = (int)(lower_bound(s, s+len, p[i].x)-s); b = (int)(lower_bound(s, s+len, p[i].y)-s+1); xx = find(a); yy = find(b); if(xx == yy){ if((parity[a]^parity[b]) != p[i].flag) break; }else if(xx < yy){ f[yy] = xx; parity[yy] = (parity[a] +parity[b] + p[i].flag) & 1; }else{ f[xx] = yy; parity[xx] = (parity[b] +parity[a] + p[i].flag) & 1; } } printf("%d\n",i-1); return 0; }