题目:
小A和小B在玩一个游戏。
首先,小A写了一个由0和1组成的序列S,长度为N。
然后,小B向小A提出了M个问题。
在每个问题中,小B指定两个数 l 和 r,小A回答 S[l~r] 中有奇数个1还是偶数个1。
机智的小B发现小A有可能在撒谎。
例如,小A曾经回答过 S[1~3] 中有奇数个1, S[4~6] 中有偶数个1,现在又回答 S[1~6] 中有偶数个1,显然这是自相矛盾的。
请你帮助小B检查这M个答案,并指出在至少多少个回答之后可以确定小A一定在撒谎。
即求出一个最小的k,使得01序列S满足第1~k个回答,但不满足第1~k+1个回答。
输入格式
第一行包含一个整数N,表示01序列长度。
第二行包含一个整数M,表示问题数量。
接下来M行,每行包含一组问答:两个整数l和r,以及回答“even”或“odd”,用以描述S[l~r] 中有奇数个1还是偶数个1。
输出格式
输出一个整数k,表示01序列满足第1~k个回答,但不满足第1~k+1个回答,如果01序列满足所有回答,则输出问题总数量。
数据范围
N≤109,M≤10000N≤109,M≤10000
输入样例:
10 5 1 2 even 3 4 odd 5 6 even 1 6 even 7 10 odd
输出样例:
3解题报告:咱们得到的是某段区间内的奇偶性,所以咱们可以转换一下思想,每个点x的存储就是从1-x的奇偶性,那么给出的区间[l,r]的奇偶性其实就是[1,l-1],[1,r]的奇偶性的异或,因为第二个区间总是包含前者的,题目给出的l,r,even/odd都是可以去证明的,咱们一开始根据题目给的信息,维护n个独立的集合,当给定信息后,实现各个集合的连接,在这个过程中判断有没有矛盾。中间涉及矛盾的判断,咱们维护一个d数组即可,d[x]存放的是x和其节点的奇偶性,当进行路径压缩的时候,d[x]需要异或所有父节点。实现两棵树的合并的时候,维护的是x以n为根节点的树,和y以m为根节点的树进行合并,d[n]^d[x]^d[y]==result(题目给出的)因为给定的数的范围比较大,所以要提前进行一下离散化处理。
ac代码:
1 //from:Onion
2 //239 奇偶游戏 带权并查集
3 #include<iostream>
4 #include<cstring>
5 #include<cstdio>
6 #include<algorithm>
7 #include<cmath>
8 using namespace std;
9 typedef long long ll;
10
11 const int maxn=1e5+100;
12 int far[maxn];
13 int d[maxn];
14 int mp[maxn<<1];
15 int n,m;
16 struct node{
17 int l,r,result;
18 }qs[maxn];
19
20 void init()
21 {
22 for(int i=0;i<maxn;i++)
23 {
24 far[i]=i;
25 d[i]=0;
26 }
27 }
28
29 int find(int x)
30 {
31 if(far[x]==x)
32 {
33 return far[x];
34 }
35 int root=find(far[x]);
36 d[x]=d[x]^d[far[x]];
37 return far[x]=root;
38 }
39
40
41 int main()
42 {
43 int n,m;
44 init();
45 scanf("%d%d",&n,&m);
46 char op[10];
47 int x,y;
48 int cnt=0;
49 for(int i=1;i<=m;i++)
50 {
51 scanf("%d%d%s",&x,&y,op);
52 x--;
53 if(op[0]=='e')
54 {
55 qs[i].l=x;
56 qs[i].r=y;
57 qs[i].result=0;
58 }
59 else
60 {
61 qs[i].l=x;
62 qs[i].r=y;
63 qs[i].result=1;
64 }
65 mp[cnt++]=x;
66 mp[cnt++]=y;
67 }
68 int flag=0;
69 sort(mp,mp+cnt);
70 n=unique(mp,mp+cnt)-mp;
71 for(int i=1;i<=m;i++)
72 {
73 x=lower_bound(mp,mp+n,qs[i].l)-mp;
74 y=lower_bound(mp,mp+n,qs[i].r)-mp;
75 int res=qs[i].result;
76 int a=find(x);
77 int b=find(y);
78 if(a==b)
79 {
80 if(d[x]^d[y]==res)
81 continue;
82 else
83 {
84 printf("%d\n",i-1);
85 flag=1;
86 break;
87 }
88 }
89 else
90 {
91 far[a]=b;
92 d[a]=d[x]^d[y]^res;
93 }
94 }
95 if(!flag)
96 printf("%d\n",m);
97 }