题意:一个长度为N的01串,M句话,每次告诉你a~b区间内有奇数个或者偶数个1,问第一个与前面矛盾的位置在哪,输出他的上一个的位置,没有错误输出M。
思路:因为N为10^9,明显开不了那么大的数组,而M只有5000,也就是说中间会有很多数字没有。我们就想到了离散化,只保存有的数字,没有的数字不开辟空间。对于每个数字需要保存两个值,一个为父节点,一个为权值。用map<int, pair<int, int> >即可,第一个int表示下标,pair中第一个int表示父节点,第二个表示权值(0表示偶数,1表示奇数)。其他的都跟之前的那道食物链的题目基本一样了。
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<string>
#include<cstdlib>
#include<map>
using namespace std;
int n, m, ans;
map<int, pair<int, int> > M;
void init()
{
ans = -1;
M.clear();
}
int Find(int x)
{
if (M[x].first == x) return x;
int t = M[x].first;
M[x].first = Find(M[x].first);
M[x].second = (M[x].second + M[t].second) % 2;
return M[x].first;
}
int main()
{
while(~scanf("%d%d", &n, &m))
{
init();
for (int i = 0; i < m; i++)
{
int x, y, t;
//string s;
//cin >> x >> y >> s;
char s[10];
scanf("%d%d%s", &x, &y, s);
x--;
if (ans != -1) continue;//已经有错了,只需要把输入即可
if (!M.count(x)) { M[x] = make_pair(x, 0); }
if (!M.count(y)) { M[y] = make_pair(y, 0); }
if (s[0] == 'e') t = 0;//偶数
else if(s[0] == 'o') t = 1;//奇数
int root1 = Find(x), root2 = Find(y);
if (root1 != root2)//根节点不同,合并
{
M[root1].first = root2;
M[root1].second = (M[y].second + t - M[x].second + 2) % 2;
}
else
{
if (abs(M[x].second - M[y].second) % 2 != t) ans = i;//根节点相同判断是否有错
}
}
if(ans == -1) ans = m;//全对
printf("%d\n", ans);
}
return 0;
}
/*
10
5
1 2 even
3 4 odd
5 6 even
1 6 even
7 10 odd
*/