hdu 2795 Billboard 转化 线段树 区间最大值

题目链接


题意:

有一个 h * w 的矩形,要用 1 * w[i] 的小矩形去覆盖它,覆盖的原则是先 topmost,再 leftmost,并且不能覆盖现有的矩形。

给出 n 组询问,问当前的小矩形能放在哪一行。


还真没看出来是棵线段树...

不过一说是线段树,就十分合理了,就是一个询问区间最大值的问题。

所以这道题的关键就是:看出来这是个线段树!


此外,细节方面的处理就是 n 和 h 取个最小值,因为对 n 个矩形有意义的覆盖范围就是最上面 n 行。


(一遍 A 真开心)

AC代码如下:

#include <bits/stdc++.h>
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define maxn 200010
struct node {
    int l, r, max, id;
}tr[maxn * 4];
int h, w, n, tot;
inline max(int a, int b) { return a > b ? a : b; }
void push_up(int rt) {
    tr[rt].max = max(tr[lson].max, tr[rson].max);
}
void build(int rt, int l, int r) {
    tr[rt].l = l; tr[rt].r = r; tr[rt].max = w;
    if (l == r) { tr[rt].id = ++tot; return; }
    int mid = l + r >> 1;
    build(lson, l, mid); build(rson, mid + 1, r);
}
void query(int rt, int x) {
    if (tr[rt].l == tr[rt].r) {
        printf("%d\n", tr[rt].id);
        tr[rt].max -= x;
        return;
    }
    if (tr[lson].max >= x) query(lson, x);
    else query(rson, x);
    push_up(rt);
}
void work() {
    h = h < n ? h : n;
    tot = 0;
    build(1, 1, h);
    for (int i = 0; i < n; ++i) {
        int x;
        scanf("%d", &x);
        if (tr[1].max < x) { printf("-1\n"); continue; }
        query(1, x);
    }
}
int main() {
    while (scanf("%d%d%d", &h, &w, &n) != EOF) work();
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值