HDU2795 Billboard(线段树)

题目链接:HDU2795.Billboard

在一个h * w的板子上贴n张海报,每张海报的面积是1 * wi,依次张贴。

要求尽量往上贴,同一行尽量往左贴,输出如果无法贴下输出-1。注意的是如果h过大的情况,因为最多20w张海报,所以如果h大于20w,就构建20w个叶子节点即可。边输入边更新即可。

稍微改了下自己的代码格式。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
#define lson l, mid, t<<1
#define rson mid+1, r, t<<1|1
#define MAX 200010
#define LL(x) (x << 1)
#define RR(x) (x << 1 | 1)
#define MID(x, y) (x + ((y - x) >> 1))
int a[MAX];
int w, h, n;
class segment_tree {
    public :
    int tree[MAX * 4];
    void pushup(int t) {
        tree[t] = w;
    }
    void build(int l, int r, int t) {
        if(l == r) {
            tree[t] = w; return;
        }
        int mid = MID(l, r);
        build(lson), build(rson);
        pushup(t);
    }
    int update(int c, int l, int r, int t) {
        if(l == r) {
            tree[t] -= c; return l;
        }
        else {
            int ret;
            int mid = MID(l, r);
            if(tree[LL(t)] >= c) ret = update(c, lson);
            else ret = update(c, rson);
            tree[t] = max(tree[LL(t)], tree[RR(t)]);
            return ret;
        }
    }
}seg;
int main() {
    while(~scanf("%d%d%d", &h, &w, &n)) {
        seg.build(1, min(h, MAX), 1);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            if(seg.tree[1] < a[i]) printf("-1\n");
            else printf("%d\n", seg.update(a[i], 1, min(h, MAX), 1));
        }
    }
    return 0;
}


posted @ 2014-09-16 12:00  gaoxiang36999  阅读(146)  评论(0)    收藏  举报