题解: https://xiaoxiaoh.blog.csdn.net/article/details/104186134
一、内容
You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn.
Write a program that:
reads the number of intervals, their end points and integers c1, ..., cn from the standard input,
computes the minimal size of a set Z of integers which has at least ci common elements with interval [ai, bi], for each i=1,2,...,n,
writes the answer to the standard output.
Input
The first line of the input contains an integer n (1 <= n <= 50000) -- the number of intervals. The following n lines describe the intervals. The (i+1)-th line of the input contains three integers ai, bi and ci separated by single spaces and such that 0 <= ai <= bi <= 50000 and 1 <= ci <= bi - ai+1.
Output
The output contains exactly one integer equal to the minimal size of set Z sharing at least ci elements with interval [ai, bi], for each i=1,2,...,n.
Sample Input
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
Sample Output
6
二、思路
- 差分约束
- 构造s[] 前缀和数组。s[i] 代表0~i中选了的数的个数。 s[0] = 0.
- 由于题目 a和b的值可能取到0,但是前缀和s~0~不好表示。 所以我们让a和b都加1,那么范围就变成1~50001。
- 构造差分约束条件:
- s~i~ >= s~i-1~ 0~i选的数的总和应该大于等于0 ~ i-1
- s~i~ - s~i-1~ <= 1 —> s~i-1~ >= s~i~ - 1 2个之差不可能大于1。因为每个数最多选一次
- s~b~ >= s~a-1~ + c [a, b]内选的数 应该大于等于c
三、代码
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int N = 5e4 + 5, M = 15e4 + 5;
struct E {
int v, w, next;
} e[M];
int n, a, b, c, len = 1, h[N], d[N];
bool vis[N];
void add(int u, int v, int w) {
e[len].w = w;
e[len].v = v;
e[len].next = h[u];
h[u] = len++;
}
int spfa() {
memset(d, -0x3f, sizeof(d));
d[0] = 0; //代表s[0] 能选的只有0个
queue<int> q;
q.push(0);
while (!q.empty()) {
int u = q.front();
q.pop();
vis[u] = false;
for (int j = h[u]; j; j = e[j].next) {
int v = e[j].v;
int w = d[u] + e[j].w;
if (w > d[v]) {
d[v] = w;
if (!vis[v]) q.push(v), vis[v] = true;
}
}
}
return d[50001]; //代表从0--50001能选的数是多少个
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= 50001; i++) {
add(i - 1, i, 0);
add(i, i - 1, -1);
}
for (int i = 1; i <= n; i++) {
scanf("%d%d%d", &a, &b, &c);
a++, b++;
add(a - 1, b, c);
}
printf("%d\n", spfa());
return 0;
}