题意:
一个01序列s,有一些关系l r odd,或者是l r even,分别代表在[l,r]区间内,有奇数个1,有偶数个1. 问最早出现冲突的下标-1.
思路:
用前缀和的思想考虑,l到r的区间,1的个数的奇偶性,就是1~(l-1)的1的个数的奇偶性和1~r的1的个数的奇偶性的关系。
如果sum[l-1]和sum[r]奇偶性相同,那么l到r的1的个数就是偶数,不同就是奇数。
用并查集去维护每个点和祖先的关系,d数组代表和祖先之间的1的个数的奇偶性,偶数为0,奇数为1。
运算规则和异或一样,偶数和偶数为偶数,奇数和奇数为偶数,奇数和偶数为奇数。
合并的时候,x,和y合并。fa[fx]=fy;要计算d[fx]。
x~y的路径:x~fx fx~fy fy~y,x和y的关系a[i].ans=d[x]^d[y]^d[fx]。
d[fx]=d[x]^d[y]^a[i].ans;
#pragma warning(disable:4996)
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<vector>
#include<map>
#include<string>
#include<set>
#include<queue>
using namespace std;
typedef long long ll;
struct node
{
int l, r, ans;//输入
};
node a[10005];
int fa[20005], d[20005];//d表示和祖先的关系,偶数0,奇数1
vector<int>vec;//用vector来离散化
int find(int x)
{
if (x == fa[x])return x;
else
{
int t = find(fa[x]);
d[x] ^= d[fa[x]];//计算和祖先的关系
return fa[x]=t;
}
}
int main()
{
int n, m, i, k;
int x, y, fx, fy;
char s[10];
scanf("%d%d", &n, &m);
for (i = 1; i <= 2 * m; i++)
{
fa[i] = i;
}
vec.clear();
for (i = 1; i <= m; i++)
{
scanf("%d%d%s", &a[i].l, &a[i].r, s);
vec.push_back(a[i].l-1);//前缀和应该是l-1
vec.push_back(a[i].r);
if (s[0] == 'o')a[i].ans = 1;//奇数个为1
else a[i].ans = 0;
}
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(), vec.end()), vec.end());
//排序去重
for (i = 1; i <= m; i++)
{
x = lower_bound(vec.begin(), vec.end(), a[i].l - 1) - vec.begin() + 1;
y = lower_bound(vec.begin(), vec.end(), a[i].r) - vec.begin() + 1;
fx = find(x); fy = find(y);
if (fx == fy)//在一个集合里面
{
if ((d[x] ^ d[y]) != a[i].ans)
//加上括号
{
printf("%d\n", i - 1);
return 0;
}
}
else
{
fa[fx] = fy; d[fx] = d[x] ^ d[y] ^ a[i].ans;
//合并
}
}
printf("%d\n", m);
return 0;
}
来源:CSDN
作者:sunnyorrainy
链接:https://blog.csdn.net/qq_43552826/article/details/104192056