并查集——奇偶性(Parity)

题目描述

有一个01序列,长度<=1000000000,现在有n信息,每条信息的形式是-a b even/odd。表示a位到第b位元素之间的元素总和是偶数/奇数。
你的任务是对于这些给定的信息,输出第一个不正确的信息所在位置-1。信息的数目不超过5000
如果信息全部正确,即可以找到一个满足要求01序列,那么输出n

输入

输入文件
第一行一个整数m表示01序列的长度,第二行一个整数n表示信息的数目。
接下来是n条信息

输出

输出第一条错误信息的位置-1.

如果没有错误信息,则输出n

样例输入

10
5
1 2 even
3 4 odd
5 6 even
1 6 even
7 10 odd

样例输出

3

这道题可以用并查集的思路做

将第三行数据的1 2看做半开半闭区间( 0 , 2 ]中的所有整数元素,他们的和是偶数,可将0当做2的父亲,他们之间的距离为0(偶数mod2的余数)

以此类推,如果为奇数,则他们之间的距离为1

那么,输入x和y,找到他们各自的父亲g和h,如果g不等于h,则无需验证,将g作为h的父亲,其距离计算公式为:

s[ h ]=( s[ x ] + m - s[ y ] )%2

其中m为x到y的和的奇偶性(看不懂就慢慢想)

如果,g等于h,则进行验证,看看abs( s[ x ] - s[ y ] )%2是否满足此语句的奇偶性

整体思路到位

接下来,由于输入的x和y最大为十亿,无法开出这么大的数组,则必须将其理想化

由于只有5000条语句,所以元素最多只有10000个,则用数组将输入的x和y装进去,要验证的时候直接数组里面找,将其在数组中的编号代替其本身进行运算

还不明白?看代码吧:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include<cstdio>  
  2. #include<cstring>  
  3. #include<cmath>  
  4. #include<algorithm>  
  5. using namespace std;  
  6. int abs(int x){return x>=0?x:-x;}  
  7. int a[10001];  
  8. int f[10001],s[10001];  
  9. int m,n,k;  
  10. int find(int x)//找父亲与离父亲的距离,顺便找沿路所有元素与离父亲的距离(看不懂?自己慢慢想)  
  11. {  
  12.     if(f[x]==0)return x;  
  13.     int xx=find(f[x]);  
  14.     s[x]+=s[f[x]];  
  15.     s[x]%=2;  
  16.     return f[x]=xx;  
  17. }  
  18. int main()  
  19. {  
  20.     int i,j;  
  21.     scanf("%d%d",&m,&n);  
  22.     for(i=1;i<=n;i++)  
  23.     {  
  24.         char c[11];  
  25.         int x,y,r1,r2;  
  26.         scanf("%d%d%s",&x,&y,c);  
  27.         if(x>m||y>m){printf("%d",i-1);return 0;}  
  28.         if(x>y)swap(x,y);  
  29.         x--;//半开半闭区间,小的元素减减  
  30.         bool p=0,q=0;  
  31.         for(j=1;j<=k;j++)//找数组中是否有x和y  
  32. <span style="white-space:pre">  </span>{  
  33.             if(a[j]==x&&!p)x=j,p=1;  
  34.             if(a[j]==y&&!q)y=j,q=1;  
  35.     }  
  36.         if(!p)a[++k]=x,x=k;//没有就将其加进去  
  37.         if(!q)  
  38.         {  
  39.             if(x!=y)a[++k]=y,y=k;//这里要注意  
  40.             else y=x;  
  41.         }  
  42.         r1=find(x),r2=find(y);  
  43.         if(r1!=r2)  
  44.         {  
  45.             if(r1>r2)swap(r1,r2);  
  46.             f[r2]=r1;  
  47.             if(c[0]=='o')s[r2]=abs(s[x]+1-s[y])%2;  
  48.             else s[r2]=abs(s[x]-s[y])%2;  
  49.         }  
  50.         else//验证  
  51.         {  
  52.             if(c[0]=='o'&&abs(s[x]-s[y])%2!=1){printf("%d",i-1);return 0;}  
  53.             if(c[0]=='e'&&abs(s[x]-s[y])%2){printf("%d",i-1);return 0;}  
  54.         }  
  55.     }  
  56.     printf("%d",n);  
  57. }  
posted @ 2017-02-24 14:04  Izayoi_Doyo  阅读(456)  评论(0编辑  收藏  举报