362. 区间
給定 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思路
/* 這一題是一定有解的,因為最壞的情況下我們可以把1~50000中的數據全部選上。 本次存在兩種做法:(1)貪心;(2)差分約束。下面使用差分約束解決這個問題。 這里可以使用前綴和的思想求解,因為前綴和中S[0]=0,所有這里將ai,bi所在的區間范圍加上一個1,區間范圍變成了[1, 50001],這樣并不影響最終的結果。 S[i]表示:前i個數中被選出數的個數。我們最終要求解的就是S50001的最小值,因此需要使用最長路徑。對于S,S需要滿足如下條件: (1)Si≥Si?1,1≤i≤50001; (2)Si?Si?1≤1?Si?1≥Si?1; (3)區間[a, b]中至少有c個數?Sb?Sa?1≥c?Sb≥Sa?1+c;需要驗證一下:從源點出發,是否一定可以走到所有的邊。根據條件(1),從i-1可以走到i,因此從0可以走到1,從1可以走到2,......,因此存在這樣的源點。*/代碼:
#include <bits/stdc++.h> using namespace std; const int N = 5e4 + 10, M = 15e4 + 10; int dist[N], st[N]; int h[N], e[M], ne[M], w[M], idx; int n;void add(int a, int b, int c) {e[idx] = b;w[idx] = c;ne[idx] = h[a];h[a] = idx++; } void spfa() {memset(dist, -0x3f, sizeof(dist));dist[0] = 0;queue<int> qu;qu.push(0);st[0] = 1;while (qu.size()){int t = qu.front();qu.pop();st[t] = 0;for (int i = h[t]; i != -1; i = ne[i]){int j = e[i];if (dist[j] < dist[t] + w[i]){dist[j] = dist[t] + w[i];if (!st[j]){st[j] = 1;qu.push(j);}}}} } int main() {scanf("%d", &n);memset(h, -1, sizeof(h));for (int i = 1; i < N; i++){add(i - 1, i, 0);add(i, i - 1, -1);}for (int i = 0; i < n; i++){int a, b, c;scanf("%d %d %d", &a, &b, &c);a++, b++;add(a - 1, b, c);}spfa();printf("%d\n", dist[50001]);return 0; }總結
- 上一篇: 数据分析入门之三种核心思维
- 下一篇: 日本 IT 圈神作之书,好懂得可怕