题意:
是男人就下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) >> 1
using 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;
}