题面
给定 n 个区间 [ai,bi]和 n 个整数 ci。
你需要构造一个整数集合 Z,使得∀i∈[1,n],Z 中满足ai≤x≤bi的整数 x 不少于 ci 个。
求这样的整数集合 Z 最少包含多少个数。
输入格式
第一行包含整数 n。
接下来n行,每行包含三个整数ai,bi,ci。
输出格式
输出一个整数表示结果。
数据范围
1≤n≤50000,
0≤ai,bi≤50000,
1≤ci≤bi−ai+1
输入样例:
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
输出样例:
6
题解
差分约束
一堆不等式, 明显是差分约束
设 s[i], 表示 0~i 区间选择了 s[i] 个数
则 s[b] - s[a - 1] >= c
只是这样的话, 不能将 -1(a >= 0, a - 1 >= -1)~5e4 每个节点连接起来
我们发现 s[i] - s[i - 1] >= 0, s[i - 1] - s[i] >= -1
这样就将所有节点全部连接起来, 由于解的存在, 无负环,
对于差分约束, 要么把所有点扔进队列, 要么选择一个初始节点
对于这道题要么把, 0~50000全扔进去, 要么从 -1, s[-1] ≡ 0
由于越界, 我们将 -1 由 5e4 + 1代替, 或者整体将区间右移, 变为 0~50001
const int N = 5e4 + 5;
const double eps = 1e-6;
int n, m, _, k;
int h[N], ne[N << 2], to[N << 2], co[N << 2], tot;
int a[N], b[N], c[N], dis[N];
bool v[N];
void add(int u, int v, int c) {
ne[++tot] = h[u]; co[h[u] = tot] = c; to[tot] = v;
}
void spfa(int s) {
queue<int> q;
memset(dis, -1, sizeof dis);
q.push(s); dis[s] = 0;
while (!q.empty()) {
int x = q.front(); q.pop(); v[x] = 0;
for (int i = h[x]; i; i = ne[i]) {
int y = to[i];
if (dis[y] >= dis[x] + co[i]) continue;
dis[y] = dis[x] + co[i];
if (!v[y]) q.push(y), v[y] = 1;
}
}
}
int main() {
sc(n);
rep(i, 1, 5e4) add(i - 1, i, 0), add(i, i - 1, -1);
add(5e4 + 1, 0, 0); add(0, 5e4 + 1, -1);
rep(i, 1, n) {
sc(a[i]), sc(b[i]), sc(c[i]); --a[i];
if (a[i] == -1) a[i] = 5e4 + 1;
add(a[i], b[i], c[i]);
}
spfa(5e4 + 1);
pr(dis[50000]);
return 0;
}
贪心
将b按照升序排列, 尽量将数字靠近 b 放置, 加上树状数组,并查集优化, 即可
const int N = 5e4 + 5;
const double eps = 1e-6;
int n, m, _, k;
int c[N], f[N];
pair<PII, int> p[N];
void add(int x, int k) {
for (; x <= 5e4; x += -x & x) c[x] += k;
}
int ask(int x) {
int ans = 0;
for (; x; x -= -x & x) ans += c[x];
return ans;
}
int find(int x) {
if (x == f[x]) return x;
return f[x] = find(f[x]);
}
int main() {
sc(n);
rep(i, 1, n) sc(p[i].fi.se), sc(p[i].fi.fi), sc(p[i].se);
rep(i, 1, 5e4 + 1) f[i] = i;
sort(p + 1, p + 1 + n);
rep(i, 1, n) {
int x = p[i].fi.se + 1, y = p[i].fi.fi + 1, cnt = p[i].se;
cnt -= ask(y) - ask(x - 1);
if (cnt <= 0) continue;
for (int j = find(y); cnt; j = f[j])
--cnt, add(j, 1), f[j] = find(j - 1), ++m;
}
pr(m);
return 0;
}