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;
}

浙公网安备 33010602011771号