hdu 3016 Man Down

这题太坑人了,虽说是线段树+dp,可是这道题的题意确实不明确,你要知道,要想从高的木板下落到低的木板上面,假设高的木板的区间为[l, r],那么你只能从点
l和点r也就是这条木板的两个端点下去,而不是从l - 1和r + 1这两个点下去(就是坑在这,让我无数次的wa);唉……这该怎么说呢。
说一下自己的思路:按照高度进行排序,高度递减,首先查找区间[l, r]中的最大值,把这个最大值记录下来,把区间[l + 1, r - 1]赋为负数(或者其他<= 0 的数都可以), 把记录下来的数加在当前
木板的权值上面,就会得到在这条木板上的最大值;当然在区间[l, r]中也会查找到出现<= 0 的数,这时候就不要在更显区间了,因为这时候已经死在上一条木板上面了。
注意:刚开始的木板如果权值+100 <= 0这时候就不需要进行其他操作了,直接输出-1就可以了
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <stack>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <set>
#include <vector>
#include <cstring>
#include <algorithm>

#define INF 0x3fffffff
#define inf -0x3f3f3f3f
#define N 100010
#define M (N << 2)
#define LL long long
#define mod 95041567

using namespace std;

struct Node {
    int h;
    int MAX;
};

struct Interval{
    int h;
    int l;
    int r;
    int val;
    bool operator < (const Interval &p) const{
        return h > p.h;
    }
};

Interval arr[N];
Node tree[M];

void build(int rt, int l, int r){
    int mid = ((r - l) >> 1) + l;
    int lc = rt << 1;
    int rc = lc | 1;
    tree[rt].MAX = -1;
    tree[rt].h = 0;
    if(l == r) return;
    build(lc, l, mid);
    build(rc, mid + 1, r);
}

void pushdown(int rt, int lc, int rc){
    if(tree[rt].h) return ;
    tree[lc] = tree[rc] = tree[rt];
}

void pushup(int rt, int lc, int rc){
    tree[rt].h = -1;
    if(tree[lc].h == tree[rc].h && ! tree[lc].h) tree[rt].h = 0;
    tree[rt].MAX = max(tree[lc].MAX, tree[rc].MAX);
}

void update_node(int rt, int l, int r, int pos, int val){
    int mid = ((r - l) >> 1) + l;
    int lc = rt << 1;
    int rc = lc | 1;
    if(r == l) {
        tree[rt].MAX = val;
        tree[rt].h = 1;
        return ;
    }
    pushdown(rt, lc, rc);
    if(pos > mid) update_node(rc, mid + 1, r, pos, val);
    else update_node(lc, l, mid, pos, val);
    pushup(rt, lc, rc);
}

void update_interval(int rt, int l, int r, int L, int R){
    int mid = ((r - l) >> 1) + l;
    int lc = rt << 1;
    int rc = lc | 1;
    if(l == L && r == R) {
        tree[rt].h = 0;
        tree[rt].MAX = -1;
        return ;
    }
    pushdown(rt, lc, rc);
    if(L > mid) update_interval(rc, mid + 1, r, L, R);
    else if(R <= mid) update_interval(lc, l, mid, L, R);
    else {
        update_interval(lc, l, mid, L, mid);
        update_interval(rc, mid + 1, r, mid + 1, R);
    }
    pushup(rt, lc, rc);
}

int query(int rt, int l, int r, int L, int R) {
    int mid = ((r - l) >> 1) + l;
    int lc = rt << 1;
    int rc = lc | 1;
    if(l == L && r == R) return tree[rt].MAX;
    pushdown(rt, lc, rc);
    int val;
    if(L > mid) val = query(rc, mid + 1, r, L, R);
    else if(R <= mid) val = query(lc, l, mid, L, R);
    else val = max(query(lc, l, mid, L, mid), query(rc, mid + 1, r, mid + 1, R));
    pushup(rt, lc, rc);
    return val;
}

int main() {
    //freopen("in.txt", "r", stdin);
    int n;
    while(scanf("%d", &n) != EOF){
        int l = INF, r = 0;
        for(int i = 0; i < n; ++ i){
            scanf("%d %d %d %d", &arr[i].h, &arr[i].l, &arr[i].r ,&arr[i].val);
            l = min(l, arr[i].l);
            r = max(r, arr[i].r);
        }
        build(1, l, r);
        sort(arr, arr + n);
        arr[0].val += 100;
        if(arr[0].val <= 0) {
            puts("-1");
            continue ;
        }
        update_node(1, l, r, arr[0].l, arr[0].val);
        update_node(1, l, r, arr[0].r, arr[0].val);
        for(int i = 1; i < n; ++ i) {
            int val = query(1, l, r, arr[i].l, arr[i].r);
            if(val <= 0) continue ;
            val += arr[i].val;
            if(arr[i].r - arr[i].l >= 2) update_interval(1, l, r, arr[i].l + 1, arr[i].r - 1);
            update_node(1, l, r, arr[i].l, val);
            update_node(1, l, r, arr[i].r, val);
        }
        int val = tree[1].MAX;
        if(val > 0) printf("%d\n", val);
        else puts("-1");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值