Codeforces 429E Points and Segments

Description

题面
题目大意:有 (n) 个区间 ([L_i,R_i]) ,你要给每一个区间染红蓝,使得每一个位置被红色染过的次数与被蓝色染过的次数差的绝对值不大于(1)

Solution

如果 (L_i->R_i+1) 连边
染色就变成了定向,那么一个点要被从左往右和从右往左经过的次数的绝对值之差不超过 (1)
发现一个环就是符合要求的,那么我们就可以试图找一个欧拉回路
考虑奇度点的处理:
我们把相邻的奇度点连起来就可以了
因为某些有交的区间并没有连边,我们用奇度点之间的边把他们连起来,这样就可以构成欧拉回路了

然后我们只需要把从左往右的边标为红色,从右往左的边标为蓝色即可

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,in[N],head[N],nxt[N<<1],to[N<<1],num=1,b[N],cnt=0,m;
int lis[N],tot=0,q[N],top=0,fr[N<<1],id[N<<1];bool vis[N],v[N<<1],ans[N];
inline void link(int x,int y,int ID){
	nxt[++num]=head[x];to[num]=y;head[x]=num;fr[num]=x;id[num]=ID;
}
struct sub{int x,y;}e[N];
inline void dfs(int x){
	vis[x]=1;
	for(int i=head[x];i;i=nxt[i]){
		head[x]=nxt[i];
		if(v[i])continue;
		v[i^1]=1;dfs(to[i]);q[++top]=i;
	}
}
int main(){
  int x,y;
  scanf("%d",&n);
  for(int i=1;i<=n;i++){
	  scanf("%d%d",&x,&y);
	  b[++cnt]=x;b[++cnt]=y+1;
	  e[i]=(sub){x,y+1};
  }
  sort(b+1,b+cnt+1);m=unique(b+1,b+cnt+1)-b-1;
  for(int i=1;i<=n;i++){
	  x=e[i].x;y=e[i].y;
	  x=lower_bound(b+1,b+m+1,x)-b;
	  y=lower_bound(b+1,b+m+1,y)-b;
	  link(x,y,i);link(y,x,i);in[x]++;in[y]++;
  }
  for(int i=1;i<=m;i++)if(in[i]&1)lis[++tot]=i;
  for(int i=1;i<=tot;i+=2)link(lis[i],lis[i+1],0),link(lis[i+1],lis[i],0);
  for(int i=1;i<=m;i++)
	  if(!vis[i])dfs(i);
  while(top){
	  if(id[q[top]])
		  ans[id[q[top]]]=(fr[q[top]]<to[q[top]]);
	  top--;
  }
  for(int i=1;i<=n;i++)printf("%d ",ans[i]);
  return 0;
}
原文地址:https://www.cnblogs.com/Yuzao/p/8486387.html