看上去并不可 dp,实际也不可 dp
考虑线段树
当前还能上车的数量可以用线段树维护
考虑把区间按右端点排序,这样就可以贪心了
并不会证明,感觉挺显然?
大概就是你让早下车的上来了而不让晚下车的来
这样可以让后边尽量上更多的
大概这样就行了
需要注意的是区间操作中都是 [l, r - 1]
因为你可以让牛都先下车再上,
这样相当于是和当前没有这些牛是一样的
表示一开始并没想到啊...
代码:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cctype> #include<cstdio> #define lson (x << 1) #define rson ((x << 1) | 1) using namespace std; const int MAXN = 20005, MAXK = 50005; struct Line{ int l, r, siz; bool operator < (const Line& b) const { return ((r == b.r) ? (l > b.l) : (r < b.r)); } }que[MAXK]; struct Node{ int minn, lzy; }t[MAXN << 2]; int n, k, c, res; inline int rd() { register int x = 0; register char c = getchar(); while(!isdigit(c)) c = getchar(); while(isdigit(c)) { x = x * 10 + (c ^ 48); c = getchar(); } return x; } inline void pushup(int x) { t[x].minn = min(t[lson].minn, t[rson].minn); return; } inline void pushdown(int x) { register int lzy = t[x].lzy; t[lson].lzy += lzy; t[rson].lzy += lzy; t[lson].minn += lzy; t[rson].minn += lzy; t[x].lzy = 0; return; } void update(int L, int R, int l, int r, int x, int val) { if(L <= l && r <= R) { t[x].lzy += val; t[x].minn += val; return; } int mid = ((l + r) >> 1); if(t[x].lzy) pushdown(x); if(L <= mid) update(L, R, l, mid, lson, val); if(mid < R) update(L, R, mid + 1, r, rson, val); pushup(x); return; } int query(int L, int R, int l, int r, int x) { if(L <= l && r <= R) return t[x].minn; int mid = ((l + r) >> 1), ans = 0x3f3f3f3f; if(t[x].lzy) pushdown(x); if(L <= mid) ans = query(L, R, l, mid, lson); if(mid < R) ans = min(ans, query(L, R, mid + 1, r, rson)); return ans; } int main() { k = rd(); n = rd(); c = rd(); update(1, n, 1, n, 1, c); for(int i = 1; i <= k; ++i) { que[i].l = rd(); que[i].r = rd(); que[i].siz = rd(); } sort(que + 1, que + k + 1); register int tmp = 0; for(int i = 1; i <= k; ++i) { tmp = min(que[i].siz, query(que[i].l, que[i].r - 1, 1, n, 1)); if(!tmp) continue; res += tmp; update(que[i].l, que[i].r - 1, 1, n, 1, -tmp); } printf("%d ", res); return 0; }