Ex - Constrained Sums题解

题目链接

题目做法

我们发现,\(L\le x_i+x_j\) 也就等价于 \(\forall t\in \mathbb{N},x_i\ge t\vee x_j\ge L-t+1\)\(R\) 同理,证明的话 ATCODER 官网写的很清晰了。
那么接下来怎么做呢?
发现 \(nm\le 10^6\),我们考虑建立一个 bool 数组 \(a_{i,j}=0/1\) 表示 \(x_i\ge j\) 是否成立
然后我们发现,\(a_{i,j}=1\rightarrow a_{i,j-1}=1\)\(a_{i,j}=0\rightarrow a_{i,j+1}=0\)
然后对于给定的 \(A_i,B_i\),我们用 2-SAT 去判断即可。

#include<bits/stdc++.h>
using namespace std;
const int N=2e6+5; 
int n,m,q,dfn[N],low[N],T,in[N],s[N],tp,num,SC[N],mx[N];
vector<int> G[N];
int get(int x,int y,int z){
	return z*(m+2)*n+(y-1)*(m+2)+x+1;
}
void tarjan(int x){
	dfn[x]=low[x]=++T;
	s[++tp]=x,in[x]=1;
	for(int v:G[x]){
		if(!dfn[v]){
			tarjan(v);
			low[x]=min(low[x],low[v]);
		}
		else if(in[v])
			low[x]=min(low[x],dfn[v]);
	}
	if(dfn[x]==low[x]){
		num++;
		while(true){
			int u=s[tp];
			tp--,in[u]=0;
			SC[u]=num;
			if(u==x) break;
		}
	}
}
int main(){
	cin>>n>>m>>q;
	for(int i=1;i<=n;i++){
		G[get(0,i,0)].push_back(get(0,i,1));
		G[get(m+1,i,1)].push_back(get(m+1,i,0));
		for(int j=1;j<=m+1;j++){
			G[get(j,i,1)].push_back(get(j-1,i,1));
			G[get(j-1,i,0)].push_back(get(j,i,0));
		}
	}
	while(q--){
		int l,r,a,b;
		cin>>a>>b>>l>>r;
		for(int i=1;i<=m;i++){
			int j=min(m+1,max(0,l-i+1));
			G[get(i,a,0)].push_back(get(j,b,1));
			G[get(j,b,0)].push_back(get(i,a,1));
			G[get(j,a,0)].push_back(get(i,b,1));
			G[get(i,b,0)].push_back(get(j,a,1));
		}
		for(int i=1;i<=m;i++){
			int j=min(m+1,max(0,r-i+1));
			G[get(i,a,1)].push_back(get(j,b,0));
			G[get(j,b,1)].push_back(get(i,a,0));
			G[get(j,a,1)].push_back(get(i,b,0));
			G[get(i,b,1)].push_back(get(j,a,0));
		}
	}
	int cnt=2*(m+2)*n;
	for(int i=1;i<=cnt;i++)
		if(!dfn[i]) tarjan(i);
	for(int i=1;i<=n;i++)
		for(int j=0;j<=m+1;j++)
		{
			if(SC[get(j,i,0)]==SC[get(j,i,1)])
				return cout<<-1,0;
			if(SC[get(j,i,1)]<SC[get(j,i,0)])
				mx[i]=j;
		}
	for(int i=1;i<=n;i++)
		cout<<mx[i]<<" ";
	return 0;
} 
posted @ 2025-04-09 21:29  I_AK_CTSC  阅读(22)  评论(0)    收藏  举报