ural 1003 Parity 并查集

题意   就是一个小孩报数字;问从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 */
原文地址:https://www.cnblogs.com/wulangzhou/p/2940528.html