AT_abc277_h [ABC277Ex] Constrained Sums
-
前言
这道题就难在很难看出是一个 2-sat 因为它不像别的 2-sat 的题一样那么一眼。
思路
观察到 \(n\times m\leq 10^6\) 所以我们可以定义 \(2\times n\times m\) 个状态,我们发现如果定义成 \(d_{i,j}\) 表示 \(x_i\) 选 \(j\) 是否可以那么就成一个 m-sat 了所以我们改一下状态,用 \(d_{i,j,0/1}\) 表示 \(x_i\geq j\) 是否可以满足条件,通俗一点就是当第三维是 \(0\) 时 \(x_i\) 大于等于 \(j\) 可行,否则 \(x_i\) 必须小于 \(j\),所以这里我们只需要使 \(x_{i,0,1}\) 恒成立和 \(x_{i,m+1,0}\) 恒成立即可,随后我们就进行分类讨论。
-
先不考虑条件,可以发现如果 \(d_{i,j,0}\) 可行那么 \(d_{i,j-1,0}\) 一定可行,所以对于所有的 \(d_{i,j,0}\) 都向 \(d_{i,j-1,0}\) 连一条边即可。
-
对于 \(d_{i,j,1}\) 同理,如果它行(这里只要小于 \(j\))那么也一定要小于 \(j+1\)。
-
对于条件中,我们可以枚举一个 \(i\) 表示其中的一个数选什么,然后能够得到另一个能取的区间 \(l1\sim r1\)。
-
然后如果 \(i>r\) 那么当前点必须取小于的那一个,就是将 \(d_{x,i,0}\to d_{x,i,1}\),然后还有一种情况就是 \(i+m\leq l\) 那么小于 \(i\) 的一定不能选,就将 \(d_{x,i,1}\to d_{x,i,0}\)。
-
最后一种就是存在满足条件的情况,对于 \(r1\) 如果一方选 \(i\) 则另一方必须选小于等于 \(r1\) 的,即 \(d_{x,i,0}\to d_{y,r1+1,1}\) 以及 \(d_{y,r1+1,0}\to d_{x,i,1}\),对于 \(l1\) 我们发现如果一方取的数小于等于 \(i\) 则另一方必须大于等于 \(l1\) 就是 \(d_{x,i,1}\to d_{y,l1+1,0}\) 以及 \(d_{y,l1+1,1}\to d_{x,i,0}\)。
然后情况就考虑完了直接跑一遍 Tarjan 在输出 scc 小的即可。
代码
#include <bits/stdc++.h> #include<ext/pb_ds/assoc_container.hpp> #include<ext/pb_ds/tree_policy.hpp> #include <ext/rope> using namespace __gnu_pbds; using namespace std; #define int long long #define pb push_back #define rep(i,x,y) for(register int i=x;i<=y;i++) #define rep1(i,x,y) for(register int i=x;i>=y;--i) #define in(x) scanf("%lld",&x) #define fire signed #define il inline il void print(int x) { if(x<0) putchar('-'),x=-x; if(x>=10) print(x/10); putchar(x%10+'0'); } int T=1; const int N=1e4+10,M=1e2+10; int n,m,q; vector<int>v[N*M*2]; int dfn[N*M*2],low[N*M*2]; int is[N*M*2]; stack<int>s; int idx; int val[N*M*2],tot; void tarjan(int x) { s.push(x); dfn[x]=low[x]=++idx; is[x]=1; for(auto to:v[x]) { if(!dfn[to]) { tarjan(to); low[x]=min(low[x],low[to]); } else if(is[to]) low[x]=min(low[x],dfn[to]); } if(low[x]==dfn[x]) { tot++; int p; do{ p=s.top(); s.pop(); val[p]=tot; is[p]=false; }while(p!=x); } } int get(int i,int j) { return (i-1)*(m+2)+j+1; } void solve() { in(n),in(m),in(q); rep(i,1,n) { v[get(i,0)+n*(m+2)].push_back(get(i,0)); v[get(i,m+1)].push_back(get(i,m+1)+n*(m+2)); rep(j,0,m+1) {//向前后连边 if(j<=m) v[get(i,j)+n*(m+2)].push_back(get(i,j+1)+n*(m+2)); if(j>=1) v[get(i,j)].push_back(get(i,j-1)); } } while(q--) { int a,b,l,r; in(a),in(b),in(l),in(r); rep(i,0,m) { int r1=min(m,r-i),l1=max(0ll,l-i+1);//判边界 if(i>r) { v[get(a,i)].push_back(get(a,i)+n*(m+2)); v[get(b,i)].push_back(get(b,i)+n*(m+2)); continue; }else { v[get(a,i)].push_back(get(b,r1+1)+n*(m+2)); v[get(b,r1+1)].push_back(get(a,i)+n*(m+2)); v[get(b,i)].push_back(get(a,r1+1)+n*(m+2)); v[get(a,r1+1)].push_back(get(b,i)+n*(m+2)); } if(i+m-1<l) { v[get(a,i)+n*(m+2)].push_back(get(a,i)); v[get(b,i)+n*(m+2)].push_back(get(b,i)); continue; }else { v[get(a,i)+n*(m+2)].push_back(get(b,l1)); v[get(b,l1)+n*(m+2)].push_back(get(a,i)); v[get(b,i)+n*(m+2)].push_back(get(a,l1)); v[get(a,l1)+n*(m+2)].push_back(get(b,i)); } } } rep(i,1,n*(m+2)*2) if(!dfn[i]) tarjan(i); rep(i,1,n*(m+2)) { if(val[i]==val[i+n*(m+2)]) { cout<<"-1\n"; return ; } } rep(i,1,n) { rep1(j,m,0) { if(val[get(i,j)]<val[get(i,j)+n*(m+2)]) { cout<<j<<' '; break; } } } return; } fire main() { while(T--) { solve(); } return false; } -

浙公网安备 33010602011771号