题解 等你哈苏德

传送门

  • 对于每个点被多少区间覆盖一类问题:将这些区间差分了试试?

将所有区间差分成 \([l, r+1)\) 的形式
发现这个 \(abs\leqslant 1\) 就很烦
可以在每个被奇数个区间覆盖的位置 \(i\) 放一个区间 \([i, i+1)\) 转化为覆盖每个位置的黑色区间数等于白色区间数
那么现在每个区间就只影响两个点
而限制是每个点连出的边一半是黑的一半是白的
那么将给每个边赋颜色转化为给每条边定向,即为要求每个点入度等于出度
于是问题变为混合图欧拉回路
可以 dinic 解决

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 200010
#define pb push_back
#define ll long long
#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, m, k;
int l[N], r[N], w[N], uni[N], usiz;

namespace task1{
	int cnt[55];
	void solve() {
		int lim=1<<m;
		for (int s=0; s<lim; ++s) {
			memset(cnt, 0, sizeof(cnt));
			for (int i=1; i<=m; ++i)
				if (s&(1<<(i-1))) {
					if (w[i]==-1 || w[i]==1) {for (int j=l[i]; j<=r[i]; ++j) ++cnt[j];}
					else goto jump;
				}
				else {
					if (w[i]==-1 || w[i]==0) {for (int j=l[i]; j<=r[i]; ++j) --cnt[j];}
					else goto jump;
				}
			for (int i=1; i<=usiz; ++i) if (abs(cnt[i])>1) goto jump;
			for (int i=0; i<m; ++i) printf((s&(1<<i))?"1 ":"0 ");
			printf("\n"); exit(0);
			jump: ;
		}
		puts("-1");
	}
}

namespace task{
	vector<int> to[N];
	int sum[N], in[N], out[N], lim;
	int head[N], dep[N], cur[N], s, t, ans, flow, ecnt=1;
	struct edge{int from, to, next, val, id;}e[N<<1];
	inline void add(int s, int t, int w, int id) {e[++ecnt]={s, t, head[s], w, id}; head[s]=ecnt;}
	bool bfs(int s, int t) {
		memset(dep, 0, sizeof(dep));
		queue<int> q;
		cur[s]=head[s]; dep[s]=1;
		q.push(s);
		while (q.size()) {
			int u=q.front(); q.pop();
			for (int i=head[u],v; ~i; i=e[i].next) {
				v = e[i].to;
				if (e[i].val && !dep[v]) {
					dep[v]=dep[u]+1;
					cur[v]=head[v];
					if (v==t) return 1;
					q.push(v);
				}
			}
		}
		return 0;
	}
	int dfs(int u, int in) {
		if (u==t||!in) return in;
		int rest=in, tem;
		for (int i=cur[u],v; ~i; cur[u]=i=e[i].next) {
			v = e[i].to;
			if (e[i].val && dep[v]==dep[u]+1) {
				tem=dfs(v, min(rest, e[i].val));
				if (!tem) dep[v]=0;
				e[i].val-=tem;
				e[i^1].val+=tem;
				rest-=tem;
				if (!rest) break;
			}
		}
		return in-rest;
	}
	void solve() {
		memset(head, -1, sizeof(head)); k=m;
		for (int i=1; i<=m; ++i) ++sum[l[i]], --sum[r[i]];
		for (int i=1; i<=n; ++i) if ((sum[i]+=sum[i-1])&1)
			++m, l[m]=i, r[m]=i+1, ++sum[i], --sum[r[m]], w[m]=-1;
		// cout<<"sum: "; for (int i=1; i<=n; ++i) cout<<sum[i]<<' '; cout<<endl;
		// cout<<"---lim---"<<endl;
		// for (int i=1; i<=m; ++i) cout<<l[i]<<' '<<r[i]<<endl;
		for (int i=1; i<=m; ++i)
			if (w[i]==1) ++out[l[i]], ++in[r[i]], to[l[i]].pb(r[i]);
			else if (w[i]==0) ++in[l[i]], ++out[r[i]], to[r[i]].pb(l[i]);
			else ++out[l[i]], ++in[r[i]], add(l[i], r[i], 1, i), add(r[i], l[i], 0, i);
		s=n+1, t=n+2; lim=ecnt;
		// cout<<"in: "; for (int i=1; i<=n; ++i) cout<<in[i]<<' '; cout<<endl;
		// cout<<"out: "; for (int i=1; i<=n; ++i) cout<<out[i]<<' '; cout<<endl;
		for (int i=1; i<=n; ++i) {
			if ((in[i]^out[i])&1) {puts("-1"); exit(0);}
			if (in[i]>out[i]) add(i, t, (in[i]-out[i])>>1, 0), add(t, i, 0, 0);
			if (in[i]<out[i]) add(s, i, (out[i]-in[i])>>1, 0), add(i, s, 0, 0), flow+=(out[i]-in[i])>>1;
		}
		while (bfs(s, t)) ans+=dfs(s, INF);
		// cout<<"flow: "<<ans<<' '<<flow<<endl;
		if (ans!=flow) {puts("-1"); exit(0);}
		for (int i=2; i<=lim; i+=2) {
			int u=e[i].from, v=e[i].to;
			if (!e[i].val) to[v].pb(u), --in[v], --out[u], ++out[v], ++in[u], w[e[i].id]=0;
			else to[u].pb(v), w[e[i].id]=1;
		}
		// cout<<"in: "; for (int i=1; i<=n; ++i) cout<<in[i]<<' '; cout<<endl;
		// cout<<"out: "; for (int i=1; i<=n; ++i) cout<<out[i]<<' '; cout<<endl;
		for (int i=1; i<=n; ++i) assert(in[i]==out[i]);
		for (int i=1; i<=k; ++i) printf("%lld ", w[i]);
		printf("\n");
	}
}

signed main()
{
	freopen("wait.in", "r", stdin);
	freopen("wait.out", "w", stdout);

	m=read(); n=read();
	for (int i=1; i<=m; ++i) {l[i]=read(); r[i]=read()+1; w[i]=read();}
	for (int i=1; i<=m; ++i) uni[++usiz]=l[i], uni[++usiz]=r[i];
	sort(uni+1, uni+usiz+1);
	usiz=unique(uni+1, uni+usiz+1)-uni-1;
	n=usiz+1;
	for (int i=1; i<=m; ++i) l[i]=lower_bound(uni+1, uni+usiz+1, l[i])-uni, r[i]=lower_bound(uni+1, uni+usiz+1, r[i])-uni;
	task::solve();

	return 0;
}
posted @ 2022-03-15 19:56  Administrator-09  阅读(1)  评论(0编辑  收藏  举报