题意:
有一很长的01序列;
给出某个范围内数的1的个数是奇数或者是偶数;
问到哪一句话为止都是对的;
思路:
因为n的非常大,达到了10亿,但实际输入只有5000行,也就是最多出现10000个不同的数字;
所以用一个map映射,来离散化;
接下来如果出现一组a,b;就相应的将a-1 (它的映射值)和 b并起来;
r为1代表奇数,为0代表偶数;
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;
const int N = 10000 + 5;
int p[N],n,m;
int l[N], r[N], ra[N];
char operat[N][5];
map<int ,int> Map;
void init() {
for(int i = 0; i <= N; i++) {
p[i] = i;
r[i] = 0;
}
return;
}
int find_p(int x) {
if(p[x] == x)
return x;
int px = p[x];
p[x] = find_p(px);
r[x] = (r[x] + r[px]) % 2;
return p[x];
}
bool Union(int x,int y,int d) {
int px = find_p(x);
int py = find_p(y);
if(px == py) {
if((r[x] - r[y] + 2) % 2 != d)
return false;
return true;
}
if(px < py) {
p[px] = py;
r[px] = (r[y] - r[x] + d + 2) % 2;
}
else {
p[py] = px;
r[py] = (r[x] - r[y] - d + 4) % 2;
}
return true;
}
int main() {
while(scanf("%d%d",&n,&m) == 2) {
Map.clear();
int pos = 1;
init();
for(int i = 0; i < m; i++) {
scanf("%d%d%s",&l[i],&ra[i],operat[i]);
if(!Map[l[i] - 1])
Map[l[i] - 1] = pos++;
if(!Map[ra[i]])
Map[ra[i]] = pos++;
}
int i;
for(i = 0; i < m; i++) {
if(operat[i][0] == 'e') {
if(!Union(Map[l[i] - 1], Map[ra[i]], 0))
break;
}else{
if(!Union(Map[l[i] - 1], Map[ra[i]], 1))
break;
}
}
printf("%d\n",i);
}
}