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

来源:互联网 发布:数据分析思路 编辑:程序博客网 时间:2024/06/06 01:30

题目链接


题意:

有一个 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 200010struct 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;}