cf1697 F. Too Many Constraints
题意:
构造长度为 、单调不降、值域为 的数组。要求满足 个条件,条件有三种类型:
1 i x
表示2 i j x
表示3 i j x
表示
思路:
很小。开 个点, 表示 ,那就转化成 2-sat 问题
- (初始限制)
,
,
为了写码方便,把值域写成 。
struct TwoSat {
int n;
vector<vector<int>> G;
vector<bool> ans;
TwoSat(int n) : n(n), G(2*n), ans(n) {}
void Or(int u, bool f, int v, bool g) { //至少一个为真
G[2*u+!f].pb(2*v+g), G[2*v+!g].pb(2*u+f);
}
void Implies(int u, bool f, int v, bool g) { //u=f → v=g
Or(u, !f, v, g);
}
void Xor(int u, bool f, int v, bool g) { //恰一个为真
Or(u, f, v, g), Or(u, !f, v, !g);
}
void Same(int u, bool f, int v, bool g) { //同时为真/假
Xor(u, !f, v, g);
}
void Must(int u, bool f) { //u=f
Or(u, f, u, f);
}
bool work() {
vector<int> id(2*n,-1), dfn(2*n,-1), low(2*n,-1), stk;
int now = 0, cnt = 0;
function<void(int)> tarjan = [&](int u) {
stk.pb(u);
dfn[u] = low[u] = now++;
for(auto v : G[u]) {
if(dfn[v] == -1) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if(id[v] == -1) low[u] = min(low[u], dfn[v]);
}
if(dfn[u] == low[u]) {
int v; do {
v = stk.back();
stk.pop_back();
id[v] = cnt;
} while (v != u);
++cnt;
}
};
for(int i = 0; i < 2*n; i++)
if(dfn[i] == -1) tarjan(i);
for(int i = 0; i < n; i++) {
if(id[2*i] == id[2*i+1]) return false;
ans[i] = id[2*i] > id[2*i+1];
}
return true;
}
};
void sol() {
int n, m, k; cin >> n >> m >> k;
int K = k + 2;
TwoSat ts(n*K); //未拆点的点数
#define p(i,x) (i)*K+x //a[i]取x的点号
for(int i = 0; i < n; i++) {
for(int x = 1; x <= k+1; x++)
ts.Implies(p(i,x), true, p(i,x-1), true);
ts.Must(p(i,1), true);
ts.Must(p(i,k+1), false);
}
for(int i = 1; i < n; i++)
for(int x = 0; x <= k+1; x++)
ts.Implies(p(i-1,x), true, p(i,x), true);
while(m--) {
int t, i, j, x; cin >> t;
if(t == 1) { //a[i]!=x
cin >> i >> x; i--;
ts.Or(p(i,x), false, p(i,x+1), true);
}
if(t == 2) { //a[i]+a[j]<=x
cin >> i >> j >> x; i--, j--;
for(int y = max(0,x-k); y <= min(k+1,x+1); y++)
ts.Implies(p(i,y), true, p(j,x-y+1), false),
ts.Implies(p(j,y), true, p(i,x-y+1), false);
}
if(t == 3) { //a[i]+a[j]>=x
cin >> i >> j >> x; i--, j--;
for(int y = max(0,x-k-1); y <= min(k,x); y++)
ts.Implies(p(i,y+1), false, p(j,x-y), true),
ts.Implies(p(j,y+1), false, p(i,x-y), true);
}
}
if(ts.work()) {
for(int i = 0, las = 0; i < n; i++) {
for(int x = 1; x <= k; x++)
if(ts.ans[p(i,x)]) las = x; //最后一个满足a[i]>=x的x
cout << las << " \n"[i == n-1];
}
}
else cout << -1 << endl;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)