hdu 3016 Man Down(線段樹區間更新+dp)
阿新 • • 發佈:2019-02-10
題意:
是男人就下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);
#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;
}