ABC216G - 01Sequence
题意
有\(m\)个条件\((l_i,r_i,x_i)\),要求构造一个长度为\(n\)的01序列\(a_1,a_2,\cdots,a_n\),满足:
- \(\forall i\in[1,m],\sum_{j=l_i}^{r_i}[a_j=1]\ge x\)
- 最小化\(\sum_{i=1}^n\)。
做法
做法1(差分约束系统)
考虑因为答案要求最小化1的个数,为了用差分约束系统做,需要将题目转化成最大化0的个数。
设\(S_i\)表示\(\sum_{i=1}^n[a_i=0]\),我们的目标是最大化\(S_n\)。
可以列出以下三条不等式:
- \(\forall i\in [1,m],S_{r_i}-S_{l_i-1}\le r_i-l_i+1-x\Rightarrow S_{r_i}\le S_{l_i-1}+r_i-l_i+1-x\)
- \(\forall i\in [1,n],0\le S_i-S_{i-1}\le 1\Rightarrow\)
- \(S_{i-1}\le S_i\)
- \(S_i\le S_{i-1}+1\)
考虑到边权非负,即无负环,直接Dijkstra
即可。
时间复杂度\(O((n+m)\log (n+m))\)。
代码:
/******************************************/
// Author:jpy_cpp //
/******************************************/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
int n, m, dis[maxn];
vector<pair<int, int>> graph[maxn];
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int,int>>> pq;
void Dijkstra() {
memset(dis, 0x3f, sizeof(dis));
dis[0] = 0;
pq.push(make_pair(0, 0));
while(!pq.empty()) {
int u = pq.top().second, d = pq.top().first;
pq.pop();
if(d != dis[u]) {
continue;
}
for(int i = 0; i < (int)graph[u].size(); i++) {
int v = graph[u][i].first, l = graph[u][i].second;
if(dis[v] > dis[u] + l) {
dis[v] = dis[u] + l;
pq.push(make_pair(dis[v], v));
}
}
}
}
void Main() {
scanf("%d%d", &n, &m);
for(int i = 0; i < m; i++) {
int l, r, x;
scanf("%d%d%d", &l, &r, &x);
graph[l - 1].push_back(make_pair(r, r - l + 1 - x));
}
for(int i = 1; i <= n; i++) {
graph[i].push_back(make_pair(i - 1, 0));
graph[i - 1].push_back(make_pair(i, 1));
}
Dijkstra();
for(int i = 1; i <= n; i++) {
printf("%d ", (dis[i] == dis[i - 1] ? 1 : 0));
}
}
int main() {
#ifdef Test
freopen("input.in","r",stdin);
freopen("output.out","w",stdout);
#endif
Main();
return 0;
}
作者:jpy_cpp