题意:一个由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;
}