1. 程式人生 > 其它 >AcWing 362. 區間

AcWing 362. 區間

題目傳送門

思路:
\(s[i]\) 表示前 \(i\) (包括\(i\)) 的數中 選擇了幾個數
所以 \(s[i] >= s[i - 1]\)
題目輸入的 \(a ,b, c\);
\(s[b] - s[a - 1] >= c\);

利用這兩個條件進行差分約束 然後 偏移量為\(1\)空出 \(a[0]\)為偏移點, 就 可以直接得到 dist[50001] 為最終答案。

#include <bits/stdc++.h>
using namespace std;
//這裡也可以把[a,b]區間往右移動一個單位,
//這樣就可以空出來S[0]這個點,作為超級原點
const int N = 50010, M = 150010;
int n;
int dist[N];

bool st[N];
//鄰接表
int e[M], h[N], idx, w[M], ne[M];
void add(int a, int b, int c) {
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}

void spfa() {
    queue<int> q;
    memset(dist, -0x3f, sizeof dist);
    dist[0] = 0;
    st[0] = true;
    q.push(0);

    while (q.size()) {
        int t = q.front();
        q.pop();
        st[t] = false;
        for (int i = h[t]; ~i; i = ne[i]) {
            int j = e[i];
            if (dist[j] < dist[t] + w[i]) {
                dist[j] = dist[t] + w[i];
                if (!st[j]) {
                    q.push(j);
                    st[j] = true;
                }
            }
        }
    }
}

int main() {
    cin >> 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;
        cin >> a >> b >> c;
        a++, b++; //區間往後移動一位
        add(a - 1, b, c);
    }
    spfa();
    printf("%d\n", dist[50001]);
    return 0;
}