hdu 3016 Man Down(线段树区间更新+dp)

来源:互联网 发布:北方金银分析软件 编辑:程序博客网 时间:2024/05/21 18:41

题意:

是男人就下100层相信很多人都玩过,这题就是简单的模拟这个游戏。
n块木板,每块木板有4个属性,高h(h>0),左边界,右边界,以及掉落在它上面,获得多少生命值,一个人从最高的木板开始往下跳,初始时生命值为100,问最后掉落到地面能获得的生命值最多为多少(如果途中生命值为≤0,那么这个人会死去),如果无法跳到地面,输出-1。

解析:

既然只能垂直下落,而且是落在最近的板上,所以其实下落后处于哪个木板是唯一确定的。
所以我们可以逆向考虑,对于任意一块木板,这块木板,可以接到从哪一块木板上面落下来的物体。
这里可以借助线段树。先将木板按h从小到大排序,初始时,更新线段树里的全部节点为地面的下标,然后往上添加木板的过程就是,单点查询每个木板的左端点和右端点,得到的下标就是当前木板能转移到的其他木板(或者地面),然后将这段区间更新为当前木板的下标。
这样就可以得到每块木板可以落到哪一块木板上了。

然后就是利用dp,求最大的权值总和,状态转移方程为:
d[line[i].lv]=max(d[line[i].lv],d[i]+line[line[i].lv].val);
d[line[i].rv]=max(d[line[i].rv],d[i]+line[line[i].rv].val);

my code

#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#define ls (o<<1)#define rs (o<<1|1)#define lson ls, L, M#define rson rs, M+1, R#define MID (L + R) >> 1using namespace std;const int N = (int)1e5 + 10;const int INF = 0x3f3f3f3f;int n;struct Line {    int h, l, r, val;    int lv, rv;    bool operator < (const Line& rhs) const {        return h < rhs.h;    }} line[N];int cov[N<<2];inline void pushDown(int o) {    if(cov[o] != -1) {        cov[ls] = cov[rs] = cov[o];        cov[o] = -1;    }}inline void pushUp(int o) {    if(cov[ls] == cov[rs])        cov[o] = cov[ls];    else cov[o] = -1;}void modify(int o, int L, int R, int ql, int qr, int val) {    if(ql <= L && R <= qr) {        cov[o] = val;        return ;    }    int M = MID;    pushDown(o);    if(ql <= M) modify(lson, ql, qr, val);    if(qr > M) modify(rson, ql, qr, val);    pushUp(o);}int query(int o, int L, int R, int pos) {    if(L == R) return cov[o];    int M = MID;    pushDown(o);    if(pos <= M) return query(lson, pos);    else return query(rson, pos);}int d[N];int main() {    int h, l, r, val;    int ql, qr;    while(~scanf("%d", &n)) {        for(int i = 1; i <= n; i++) {            scanf("%d%d%d%d", &h, &l, &r, &val);            line[i] = (Line){h, l, r, val};        }        sort(line+1, line+n+1);        modify(1, 0, N, 0, N, 0);        for(int i = 1; i <= n; i++) {            line[i].lv = query(1, 0, N, line[i].l);            line[i].rv = query(1, 0, N, line[i].r);            modify(1, 0, N, line[i].l, line[i].r, i);        }        memset(d, 0, sizeof(d));        d[n] = 100 + line[n].val;        for(int i = n; i > 0; i--){            if(d[i] <= 0) continue;            d[line[i].lv]=max(d[line[i].lv], d[i]+line[line[i].lv].val);            d[line[i].rv]=max(d[line[i].rv], d[i]+line[line[i].rv].val);        }        printf("%d\n",d[0] > 0 ? d[0] : -1);    }    return 0;}
0 0
原创粉丝点击