题意 就是一个小孩报数字;问从a ~ b 是奇还是偶 然后出现矛盾时,判断矛盾是什么时候出现;输出前面有多少句是对的
解题 这题 确实是有点难度;一开始怎么也没有想清楚;想清楚还是蛮简单的;首先要明白一个原理,那就是从哪里到哪里是奇偶 有断点就可以决定,所以只与端点有关系;所以把所有想法都放到端点上来;端点与端点之间只有 奇偶性不同和相同的关系;可以用并查集 + ^(亦或运算)同时操作解决;首先如果两个点有关系,则把这两个点放在同一个集合里面,祖先到祖先的距离永远赋值为0 然后同一个集合的元素还好说;在进行 压缩路径的时候 同时更新一下 距离;如果两个不同的集合要变成一个集合;同理 和上一个题目一样,列举一个方程式;就出来了;~~
1 #include<iostream> 2 #include<stdio.h> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 struct date 8 { 9 int sta,end,vis; 10 }cnt[50005]; 11 int arr[100009],f[100009],r[100009]; 12 13 int find( int x ) 14 { 15 if( f[x] != x ) 16 { 17 int t = find( f[x]); 18 r[x] ^= r[f[x]]; 19 f[x] = t; 20 return t; 21 } 22 return x; 23 } 24 25 int search( int l,int r,int key ) 26 { 27 int mid = ( l + r )>>1; 28 if( arr[mid] == key ) return mid; 29 if( arr[mid] >= key ) return search( l,mid,key ); 30 else return search( mid+1,r,key ); 31 } 32 33 int main( ) 34 { 35 int len,N,sta,end,i,k,t; 36 char str[7]; 37 while( scanf("%d",&len) && len != -1 ) 38 { 39 scanf("%d",&N); k = 0; 40 for( i = 1; i <= N; i++ ) 41 { 42 scanf("%d%d%s",&cnt[i].sta,&cnt[i].end,&str); 43 if( str[0] == 'e' ) cnt[i].vis = 0; 44 else cnt[i].vis = 1; 45 arr[++k] = cnt[i].sta-1; 46 arr[++k] = cnt[i].end; 47 } 48 sort( &arr[1],&arr[1]+k ); 49 t = 1; 50 for( i = 2; i <= k; i++ ) 51 if( arr[i] != arr[t] ) 52 arr[++t] = arr[i]; 53 for( i = 0; i <= 100001; i++ ) 54 f[i] = i,r[i] = 0; 55 for( i = 1; i <= N; i++ ) 56 { 57 sta = cnt[i].sta-1; end = cnt[i].end; 58 sta = search( 1,t,sta )+1; 59 end = search( 1,t,end )+1; 60 int a = find(sta); 61 int b = find(end); 62 f[a] = b; 63 if( a == b ) 64 { 65 if( cnt[i].vis && r[sta] == r[end] ) 66 { 67 printf("%d\n",i-1);break; 68 } 69 if( !cnt[i].vis && r[sta] != r[end] ) 70 { 71 printf("%d\n",i-1);break; 72 } 73 } 74 else r[a] = r[sta]^r[end]^cnt[i].vis; 75 } 76 if( i == N+1 ) printf("%d\n",N); 77 } 78 return 0; 79 } 80 /* 81 10 5 82 1 2 even 83 3 4 old 84 5 6 even 85 1 6 even 86 7 8 old 87 */