CF429E.Points and Segments

题目链接

题解

首先只要考虑每段区间的 l l l r + 1 r+1 r+1。对于区间覆盖问题,联想到欧拉回路的一个性质:把点排成一条直线,每个点被欧拉回路正方向覆盖的次数与反方向相等(一条边覆盖的点不包括左端点或右端点)。

于是把 l l l r + 1 r+1 r+1连边,若能跑出欧拉回路即可(即所有点度数都为偶数)。否则,每相邻的两个度数为奇的点之间连边,这样可以保证跑出欧拉回路,且每个点最多被一条原来不存在的边覆盖。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
int n,m,a[N],hd[N],to[N],nx[N],id[N],du[N],tt=1;
void add(int u,int v,int d){
	nx[++tt]=hd[u]; to[hd[u]=tt]=v; id[tt]=d; du[v]++;
	//cout<<u<<" "<<v<<endl;
}
bool vs[N]; int ans[N],l[N],r[N];
void dfs(int x,int u){
	for(int e=hd[u];e;e=nx[e]) if(!vs[e]){
		int v=to[e]; if(du[v]&1 && v!=x) continue;
		du[u]--; du[v]--; ans[id[e]]=(u<v); vs[e]=vs[e^1]=1;
		if(v!=x) dfs(x,v);
		break;
	}
}
int main()
{
	srand(time(0));
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	cin>>m;
	for(int i=1;i<=m;i++) scanf("%d%d",&l[i],&r[i]),r[i]++,a[++n]=l[i],a[++n]=r[i];
	sort(a+1,a+n+1); n=unique(a+1,a+n+1)-a-1;
	for(int i=1;i<=m;i++){
		int u=lower_bound(a+1,a+n+1,l[i])-a,v=lower_bound(a+1,a+n+1,r[i])-a;
		add(u,v,i),add(v,u,i);
	}
	for(int i=1,j=0;i<=n;i++) if(du[i]&1){
		if(!j) j=i;
		else add(j,i,0),add(i,j,0),j=0;
	}
	for(int i=1;i<=n;i++) while(du[i]) dfs(i,i);
	for(int i=1;i<=m;i++) printf("%d ",ans[i]); puts("");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值