HDU 2795 Billboard(线段树)

题目链接:HDU 2795 Billboard

【题意】给你一张h*w(1 <= h,w <= 10^9)大小的海报,上面会张贴一些数量为n(1<=n<=200000)高度为1宽度不定的小纸条,然后输入一些小纸条的宽度,求出它所张贴的高度。小纸条张贴是尽量靠左靠上,如果不能张贴,就输出-1.

【思路】海报的数据特别大,思路就是用线段树来优化,但是高度h高达10^9,直接建树肯定会爆,但纸条最多有n(200000)张,于是可以用len = min(h, n)来进行建线段树[1, len],节点维护的是海报每一行的可利用空白宽度。每次查询优先往左子树查询,查询之后还要更新数据,保留新的可利用空白宽度。

【吐槽】第一次自己来写线段树,以前对线段树一直是一种仰望的心态,的确是很牛逼的算法,有二分的思想在里面,转换为logn的强大力量。但是真的不好写啊哭数据结构就是伤不起。

下面贴AC代码:

/*
** HDU 2795 Billboard
** Created by Rayn @@ 2014/05/08
** 线段树
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX = 200005;

int tree[MAX<<2];

void BuildTree(int k, int l, int r, int val)
{
    tree[k] = val;
    if(l == r)
        return ;
    int mid = (l + r) / 2;
    BuildTree(k<<1, l, mid, val);
    BuildTree(k<<1|1, mid+1, r, val);
}
int Query(int k, int l, int r, int val)
{
    if(l == r && tree[k] >= val)
    {
        tree[k] -= val;
        return l;
    }
    int mid = (l + r) / 2, ans;
    if(tree[k<<1] >= val)
        ans = Query(k<<1, l, mid, val);
    else if(tree[k<<1|1] >= val)
        ans = Query(k<<1|1, mid+1, r, val);
    else
        ans = -1;
    tree[k] = max(tree[k<<1], tree[k<<1|1]);
    return ans;
}
int main()
{
    int h, w, n;
    while(scanf("%d%d%d", &h, &w, &n) != EOF)
    {
        h = min(h, n);
        BuildTree(1, 1, h, w);
        for(int i=0; i<n; ++i)
        {
            int wid;
            scanf("%d", &wid);
            printf("%d\n", Query(1, 1, h, wid));
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值