[省选集训2022] 模拟赛14

wait

题目描述

有一些黑白区间 \([l_i,r_i]\),有些区间已经被指定了颜色,有些区间还没有。你需要指定未染色区间的颜色,使得对于数轴上每个点,覆盖他的黑区间和白区间个数差的绝对值 \(\leq 1\)

\(n\leq 10^9,m\leq 3\cdot 10^4\)

解法

事实上看到这个差的绝对值 \(\leq 1\) 我的 \(\tt DNA\) 就有反应了,好像集训队作业中有类似的题,但是我没有回想起来,只是差值绝对值 \(\leq 1\) 这个问题,它可能指向欧拉回路。

可以把点按被覆盖次数分为奇覆盖和偶覆盖,首先考虑都是偶覆盖的情况。这时有一个特别强的限制:因为所有点最后差值都是 \(0\),所以我们把黑看成 \(1\),白看成 \(-1\),那么差分数组一定全为 \(0\)

对于黑区间,它对差分数组的影响是 \(s[l_i]\leftarrow +1\)\(s[r_i+1]\leftarrow -1\);对于白区间,它对差分数组的影响是 \(s[l_i]\leftarrow -1\)\(s[r_i+1]\leftarrow +1\),我们可以把差分数组看成度数,那么差分数组全为 \(0\) 就等价于多源点欧拉回路的充要条件:入度\(=\)出度。

所以黑区间可以看成 \(l_i\rightarrow r_i+1\) 的边,白区间可以看成 \(r_i+1\rightarrow l_i\) 的边,现在我们要把未染色的边定向,使得此图存在欧拉回路,那么就是一个混合图欧拉回路,可以用网络流解决。

那么存在奇覆盖怎么做呢?考虑把这些点添加一条 \(i - i+1\) 未定向的边,如果度数是 \(-1\) 这条边就会把度数调整成 \(0\),如果度数是 \(1\) 这条边就会把度数调整成 \(0\),直接跑网络流即可。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int M = 60005;
const int inf = 0x3f3f3f3f;
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int n,m,l[M],r[M],w[M],a[M],in[M],pre[M];
int S,T,tot=1,f[M],d[M],cur[M],id[M];
struct edge{int v,c,next;}e[M*10];
void add(int u,int v,int c)
{
	e[++tot]=edge{v,c,f[u]},f[u]=tot;
	e[++tot]=edge{u,0,f[v]},f[v]=tot;
}
int bfs()
{
	queue<int> q;q.push(S);d[S]=1;
	for(int i=1;i<=T;i++) d[i]=0;
	while(!q.empty())
	{
		int u=q.front();q.pop();
		if(u==T) return 1;
		for(int i=f[u];i;i=e[i].next)
		{
			int v=e[i].v;
			if(!d[v] && e[i].c>0)
			{
				d[v]=d[u]+1;
				q.push(v);
			}
		}
	}
	return 0;
}
int dfs(int u,int ept)
{
	if(u==T) return ept;
	int tmp=0,flow=0;
	for(int i=f[u];i;i=e[i].next)
	{
		int v=e[i].v;
		if(d[v]==d[u]+1 && e[i].c>0)
		{
			tmp=dfs(v,min(ept,e[i].c));
			if(!tmp) continue;
			ept-=tmp;flow+=tmp;
			e[i].c-=tmp;e[i^1].c+=tmp;
			if(!ept) break;
		}
	}
	return flow;
}
signed main()
{
	freopen("wait.in","r",stdin);
	freopen("wait.out","w",stdout); 
	n=read();read();
	for(int i=1;i<=n;i++)
	{
		l[i]=read();r[i]=read();w[i]=read();
		a[++m]=l[i];a[++m]=++r[i];
	}
	sort(a+1,a+1+m);m=unique(a+1,a+1+m)-a-1;
	for(int i=1;i<=n;i++)
	{
		l[i]=lower_bound(a+1,a+1+m,l[i])-a;
		r[i]=lower_bound(a+1,a+1+m,r[i])-a;
		pre[l[i]]++;pre[r[i]]--;
		if(w[i]==0)
			in[l[i]]--,in[r[i]]++;
		else if(w[i]==1)
			in[l[i]]++,in[r[i]]--;
		else
		{
			in[l[i]]--;in[r[i]]++;//0
			add(r[i],l[i],1);id[i]=tot;
		}
	}
	for(int i=1;i<=m;i++)
		if((pre[i]+=pre[i-1])&1)
		{
			in[i]--;in[i+1]++;
			add(i+1,i,1);
		}
	S=0;T=m+1;int sum=0;
	for(int i=1;i<=m;i++)
	{
		if(in[i]%2) {puts("-1");return 0;}
		if(in[i]>0) add(S,i,in[i]/2),sum+=in[i]/2;
		if(in[i]<0) add(i,T,(-in[i])/2);
	}
	while(bfs())
	{
		for(int i=S;i<=T;i++) cur[i]=f[i];
		sum-=dfs(S,inf);
	}
	if(sum) {puts("-1");return 0;}
	for(int i=1;i<=n;i++)
	{
		if(w[i]!=-1) printf("%d ",w[i]);
		else printf("%d ",e[id[i]].c?1:0);
	}
}
posted @ 2022-03-15 15:43  C202044zxy  阅读(204)  评论(0编辑  收藏  举报