题目:

n个用户上网,有m条网线。每条网线规定只[L,R]区间中的用户能上,且最多同时上v人。问最多能同时几人在线。
组数不超过10
n,m(1<=n,m<=10000)


做法:

看这个题面,第一时间想到最大流。当然看到数据范围发现有点勉强。(但跑得还挺快
考虑朴素的建图:
1、源点s和每个用户建边,流量1;
2、每个用户和能连上的网线建边,流量1;
3、每条网线和汇点t建边,流量v。
但是这样边数就太多了。想想,每条网线都要连R-L+1条边其实是没必要,考虑可以用线段树维护整段区间建边,这样可以减少很多的边。
然后用sap跑最大流。


代码:

#include <bits/stdc++.h>
#define lson rt<<1
#define rson rt<<1|1
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define debug(a) cout << #a ": " << a << endl
using namespace std;
typedef long long ll;
inline int read(void){
    char ch = getchar();
    int ans = 0;
    while (!isdigit(ch)) ch = getchar();
    while (isdigit(ch)) ans = ans*10 + ch-'0', ch = getchar();
    return ans;
}
const int N = 7e4 + 7;
const int M = 2e6 + 7;
const int inf = 0x3f3f3f3f;
int n, m;
struct edge{
    int v, cap, nxt;
}e[M];
int tot, head[N];
int tag, T[N<<2];
int dep[N], gap[N], q[M], stk[M], top, tail, cur[N];
void init(void){
    tot = 0; memset(head, -1, sizeof head);
}
void addedge(int u, int v, int f){
    e[tot] = (edge){v, f, head[u]}; head[u] = tot++;
    e[tot] = (edge){u, 0, head[v]}; head[v] = tot++;
}
void build(int l, int r, int rt){
    T[rt] = ++tag;
    if (l == r){
        addedge(0, T[rt], 1);
        return;
    } 
    int mid = (l+r) >> 1;
    build(l, mid, lson); build(mid+1, r, rson);
    addedge(T[lson], T[rt], mid-l+1);
    addedge(T[rson], T[rt], r-mid);
}
void update(int L, int R, int p, int l, int r, int rt){
    if (L <= l && r <= R){
        addedge(T[rt], p, r-l+1); return;
    }
    int mid = (l+r) >> 1;
    if (L <= mid) update(L, R, p, l, mid, lson);
    if (R > mid) update(L, R, p, mid+1, r, rson);
}
void bfs(int s, int t){
    top = tail = 0;
    for (int i = s; i <= t; ++i){
        dep[i] = -1, gap[i] = 0;
    }
    gap[0] = 1;
    dep[t] = 0;
    q[tail++] = t;
    while (top != tail){
        int u = q[top++];
        for (int i = head[u]; i != -1; i = e[i].nxt){
            int v = e[i].v;
            if (dep[v] == -1){
                dep[v] = dep[u]+1;
                gap[dep[v]]++;
                q[tail++] = v;
            }
        }
    }
}
int sap(int s, int t, int N){
    bfs(s, t);
    for (int i = s; i <= t; ++i) cur[i] = head[i];
    top = 0;
    int u = s;
    int ans = 0;
    while (dep[s] < N){
        if (u == t){
            int mn = inf;
            int inser;
            for (int i = 0; i < top; ++i){
                if (mn > e[stk[i]].cap){
                    mn = e[stk[i]].cap;
                    inser = i;
                }
            }
            for (int i = 0; i < top; ++i){
                e[stk[i]].cap -= mn;
                e[stk[i]^1].cap += mn;
            }
            ans += mn;
            top = inser;
            u = e[stk[top]^1].v;
            continue;
        }
        bool flag = false;
        int v;
        for (int i = cur[u]; i != -1; i = e[i].nxt){
            v = e[i].v;
            if (e[i].cap && dep[v]+1 == dep[u]){
                flag = true;
                cur[u] = i;
                break;
            }
        }
        if (flag){
            stk[top++] = cur[u];
            u = v;
            continue;
        }
        int mn = N;
        for (int i = head[u]; i != -1; i = e[i].nxt){
            if (e[i].cap && dep[e[i].v] < mn){
                mn = dep[e[i].v];
                cur[u] = i;
            }
        }
        gap[dep[u]]--;
        if (!gap[dep[u]]) return ans;
        dep[u] = mn + 1;
        gap[dep[u]]++;
        if (u != s) u = e[stk[--top]^1].v;
    }
    return ans;
}
int main(void){
    while (scanf("%d%d", &n, &m) != EOF){
        init();
        tag = 0; build(1, n, 1);
        int s = 0, t = tag+m+1;
        for (int i = 1; i <= m; ++i){
            int l = read(), r = read(), v = read();
            update(l, r, tag+i, 1, n, 1);
            addedge(tag+i, t, v);
        }
        printf("%d\n", sap(s, t, t+1));
    }
    return 0;
}