你的朋友写下一串包含1和0的串让你猜,你可以从中选择一个连续的子串(例如其中的第3到第5个数字)问他,该子串中包含了奇数个还是偶数个1,他会回答你的问题,然后你可以继续提问......你怀疑朋友的答案可能有错,或说同他之前的答案相互矛盾,例如:1 - 2 奇数,3 - 4 奇数,那么可以确定1 - 4 一定是偶数,如果你的朋友回答是奇数,就产生了矛盾。给出所有你朋友的答案,请你找出第一个出现矛盾的答案。
Input
第1行:2个数N, Q,N为串的长度,Q为询问的数量。(2 <= N <= 100000, 2 <= Q <= 50000) 第2 - Q + 1行:每行包括两个数以及一个字符串来描述朋友的回答,2个数中间用空格分隔,分别表示区间的起点和终点,后面的字符为"even"或"odd",表示朋友的答案。
Output
输出1个数,表示朋友的答案中第一个错误答案的位置,如果所有答案均不矛盾,则输出-1。
Input示例
10 5 1 2 even 3 4 odd 5 6 even 1 6 even 7 10 odd
Output示例
4
如果S[a]到S[b]是偶数,说明S[a-1]和S[b]是相同的值。划分到一个集里面去。
如果S[a]到S[b]是奇数,说明S[a-1]和S[b]是不同的值。将S[a-1+n]和S[b]划分到一个集里面去。
代码:
#pragma warning(disable:4996)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <cmath>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
#define INF 0x3fffffff
const int mod = 1e9 + 7;
const int maxn = 200005;
int n, q;
int pre[maxn];
void init()
{
int i;
for (i = 0; i < maxn; i++)
{
pre[i] = i;
}
}
int fa(int x)
{
while (pre[x] != x)
{
x = pre[x];
}
return x;
}
void uni(int x, int y)
{
x = fa(x);
y = fa(y);
if (x > y)
{
x ^= y ^= x ^= y;
}
pre[x] = y;
}
void solve()
{
int i, flag;
int s, e;
char ch[10];
scanf("%d%d", &n, &q);
flag = 0;
for (i = 1; i <= q; i++)
{
scanf("%d%d%s", &s, &e, ch);
if (flag)continue;
if (strcmp(ch, "even") == 0)
{
if (fa(s - 1 + n) == fa(e) && fa(s - 1) == fa(e + n))
{
flag = i;
}
else
{
uni(s - 1, e);
uni(s - 1 + n, e + n);
}
}
else
{
if (fa(s - 1) == fa(e) && fa(s - 1 + n) == fa(e + n))
{
flag = i;
}
else
{
uni(s - 1, e + n);
uni(s - 1 + n, e);
}
}
}
if (flag)
{
printf("%d\n", flag);
}
else
{
puts("-1");
}
}
int main()
{
//freopen("i.txt", "r", stdin);
//freopen("o.txt", "w", stdout);
init();
solve();
//system("pause");
return 0;
}