[HDU 2795]Billboard[线段树]

来源:互联网 发布:无锡市软件行业协会 编辑:程序博客网 时间:2024/06/03 20:39

题目链接:[HDU 2795]Billboard[线段树]

题意分析:

有一个高度为h,宽度为w的广告板,给出n个海报,每个海报高度1,宽度x。问能否贴到广告板上,能输出贴到的行,否则输出-1。每张海报必须贴到能贴部分的最左上角。

解题思路:

用线段树区间存:区间中还能贴的最大宽度;每次查询整个区间,满足就继续,否则返回,当l == r时说明查询到了最满足的行,然后进行更新。

个人感受:

意淫了一下,然后第一发是用h当区间最高点,re了。然后改成h = min(h, n)(海报如果贴满顶多贴n行)。顺利过了,自己都觉得神奇,难得意淫。

具体代码如下:

#include<iostream>#include<cstdio>#define root 1, h, 1#define lson l, m, rt << 1#define rson m + 1, r, rt << 1 | 1using namespace std;const int MAXN = 2e5 + 111;int lef[MAXN << 2], ans, h, w, n;void push_up(int rt){    lef[rt] = max(lef[rt << 1], lef[rt << 1 | 1]);}void update(int x, int val, int l, int r, int rt){    if (l == r)    {        lef[rt] -= val;        return;    }    int m = (l + r) >> 1;    if (x <= m) update(x, val, lson);    else update(x, val, rson);    push_up(rt);}bool query(int val, int l, int r, int rt){    if (lef[rt] < val) return 0;    if (l == r)    {        ans = l;        update(ans, val, root);        return 1;    }    int m = (l + r) >> 1;    if (query(val, lson)) return 1;    if (query(val, rson)) return 1;    return 0;}int main(){    while (~scanf("%d%d%d", &h, &w, &n))    {        h = min(h, n);        for (int i = 1; i <= n << 2; ++i) lef[i] = w;        int x;        for (int i = 0; i < n; ++i)        {            scanf("%d", &x);            if (query(x, root)) printf("%d\n", ans);            else puts("-1");        }    }    return 0;}


0 0