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