参考博客
题意:给m个区间和这个区间内1的个数是奇还是偶,然后输出第一个和前面相矛盾的区间的序号
思路:首先区间最大值有1e9,数组开不出来,而数据的输入量却很小,最多也就10000个数,所以先进行离散化处理区间的标号
区间内1的数量为偶就看成0,否则为1;因为我们不关心具体的数量;(x,y)的1的个数为奇数时,也就是x-1到y中间的1的个数为奇数,故可用(x-1) <- y,其中rela[y]=1,代表y和他的父节点之前的1的个数为奇数。其他就和食物链差不多。主要在于要看到(x,y)的1的个数和x-1<-y之间转换。
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<time.h>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<functional>
#include<stack>
#include<map>
#include<queue>
#define mod (1000000007)
#define middle (l+r)>>1
#define SIZE 10000+10
#define lowbit(x) (x&(-x))
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long ll;
const int inf_max = 0x3f3f3f3f;
const ll Linf = 9e18;
const int maxn = 50000+10;
const double eps=0.0001;
using namespace std;
int n,m,cnt,a[maxn],f[maxn],val[maxn],tmp[maxn];
struct Seg
{
int l,r;
}seg[maxn];
int myfind(int x)
{
if(x==f[x])
return f[x];
int t=f[x];
f[x]=myfind(f[x]);
val[x]=(val[t]+val[x])%2;
return f[x];
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
int flag=0;
for(int i=0;i<=m<<1;i++)
{
f[i]=i;val[i]=0;tmp[i]=0;
}
cnt=0;
for(int i=1;i<=m;i++)
{
char s[10];
scanf("%d%d%s",&seg[i].l,&seg[i].r,s);
tmp[i]=(s[0]=='e')?0:1;
a[cnt++]=seg[i].l;
a[cnt++]=seg[i].r;
}
sort(a,a+cnt);
int siz=unique(a,a+cnt)-a,ans=1;
for(int i=1;i<=m;i++)
{
int l=lower_bound(a,a+siz,seg[i].l)-a+1;//返回的是下标,完全可能是0
int r=lower_bound(a,a+siz,seg[i].r)-a+1;
l--;
int fl=myfind(l),fr=myfind(r);
//printf("l=%d,r=%d,fl=%d,fr=%d\n",l,r,fl,fr);
if(fl!=fr)
{
f[fr]=fl;
val[fr]=(val[l]+tmp[i]-val[r]+2)%2;
}
else
{
if(tmp[i]!=(val[r]-val[l]+2)%2)
{
flag=1;
//printf("haf\n");
ans=i;
break;
}
}
}
// for(int i=0;i<=7;i++)
// {
// printf("f[%d]=%d,val[%d]=%d\n",i,f[i],i,val[i]);
// }
if(flag)
printf("%d\n",ans-1);
else
printf("%d\n",m);
}
return 0;
}