HDU_3016
为了处理起来方便,我们可以先将plank对h排个序,最后补一个(0,100000)的value为0的plank。我们可以用f[i]表示跳到第i个plank时value和的最大值进行dp,每次在寻找可以由哪些plank落到第i个plank上时可以借助线段树。
#include<stdio.h> #include<string.h> #include<stdlib.h> #define MAXD 100010 int N, M, f[MAXD], num[4 * MAXD], col[MAXD]; struct Plank { int h, x1, x2, value; }plank[MAXD]; int cmp(const void *_p, const void *_q) { Plank *p = (Plank *)_p, *q = (Plank *)_q; return p->h > q->h ? -1 : 1; } void init() { int i, j, k; M = 100000; for(i = 0; i < N; i ++) scanf("%d%d%d%d", &plank[i].h, &plank[i].x1, &plank[i].x2, &plank[i].value); qsort(plank, N, sizeof(plank[0]), cmp); plank[N].h = 0, plank[N].x1 = 0, plank[N].x2 = M, plank[N].value = 0; } void build(int cur, int x, int y) { int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1; num[cur] = 0; if(x == y) return ; build(ls, x, mid); build(rs, mid + 1, y); } void update(int cur) { num[cur] = num[cur << 1] + num[(cur << 1) | 1]; } void Insert(int cur, int x, int y, int k, int c) { int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1; if(x == y) { num[cur] = 1; col[x] = c; return ; } if(k <= mid) Insert(ls, x, mid, k, c); else Insert(rs, mid + 1, y, k, c); update(cur); } void Erase(int cur, int x, int y, int &ans) { int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1; if(x == y) { if(f[col[x]] > ans) ans = f[col[x]]; num[cur] = 0; return ; } if(num[ls]) Erase(ls, x, mid, ans); if(num[rs]) Erase(rs, mid + 1, y, ans); update(cur); } void refresh(int cur, int x, int y, int s, int t, int &ans) { int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1; if(x >= s && y <= t) { if(num[cur]) Erase(cur, x, y, ans); return ; } if(mid >= s) refresh(ls, x, mid, s, t, ans); if(mid + 1 <= t) refresh(rs, mid + 1, y, s, t, ans); update(cur); } void solve() { int i, j, k, ans; build(1, 0, M); f[0] = 100 + plank[0].value; if(f[0] > 0) Insert(1, 0, M, plank[0].x1, 0), Insert(1, 0, M, plank[0].x2, 0); for(i = 1; i <= N; i ++) { ans = -plank[i].value; refresh(1, 0, M, plank[i].x1, plank[i].x2, ans); f[i] = ans + plank[i].value; if(f[i] > 0) Insert(1, 0, M, plank[i].x1, i), Insert(1, 0, M, plank[i].x2, i); } printf("%d\n", f[N] > 0 ? f[N] : -1); } int main() { while(scanf("%d", &N) == 1) { init(); solve(); } return 0; }