HDU 2795 Billboard (线段树 单点更新 区间求最大值)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2795

题意:有一块h*w 的广告版,有n块1*w[i]的广告,就着放广告尽量在顶上,尽量先放左边的原则,问在第几行能把广告放下,如果放不下,就打印-1;

思路:我们可以根据每一行建树,每一个子叶表示每一行的容量,而节点存放子节点的最大值,然后从最顶到底,快速查找能存放下广告的一行。

总之还是简单的线段树问题,难点在于抽象模型。

#include <iostream>
#include <cstdio>
#define MID (l + r) >> 1
#define LS rt << 1
#define RS rt << 1 | 1
#define LSON l,m,rt << 1
#define RSON m + 1,r,rt << 1 | 1
#define MAX 999999

using namespace std;

int imax[MAX << 2];

inline void pushup(int rt)
{
    imax[rt] = max(imax[LS],imax[RS]);
}

void build(int w,int l,int r,int rt)
{

    if(l == r)
    {
        imax[rt] = w;
        return ;
    }

    int m = MID;

    build(w,LSON);
    build(w,RSON);

    pushup(rt);
}

int query(int x,int l,int r,int rt)
{
    if(l == r)
    {
        imax[rt] -= x;
        return l;
    }

    int m = MID;

    int ret = (imax[LS] >= x) ? query(x,LSON) : query(x,RSON);

    pushup(rt);

    return ret;
}

int main()
{
    int h,w,n;

    while(~scanf("%d%d%d",&h,&w,&n))
    {
        //优化:如果空间远远更能够h>n,那么就让h=n(一行一条广告)
        if(h > n)
            h = n;
        build(w,1,h,1);

        while(n--)
        {
            int x;
            scanf("%d",&x);

            if(imax[1] < x)    //如果最顶端没有位置
                puts("-1");
            else
                printf("%d\n",query(x,1,h,1));
        }
    }
    return 0;
}
时间: 2024-10-17 10:20:05

HDU 2795 Billboard (线段树 单点更新 区间求最大值)的相关文章

HDU 2795 Billboard (线段树单点更新 &amp;&amp; 求区间最值位置)

题意 : 有一块 h * w 的公告板,现在往上面贴 n 张长恒为 1 宽为 wi 的公告,每次贴的地方都是尽量靠左靠上,问你每一张公告将被贴在1~h的哪一行?按照输入顺序给出. 分析 : 这道题说明了每一次贴都尽量选择靠上靠左的位置,那既然这样,我们以1~h建立线段树,给每一个叶子节点赋值初值 w 表示当前行最大能够容纳宽度为 w 的公告纸,那么对于某一输入 wi 只要在线段树的尽量靠左的区间找出能够容纳这张公告的位置(即叶子节点)然后减去 wi 即可,需要对query()函数进行一点改造,将

HDU 2795 Billboard(线段树,单点更新)

D - Billboard Crawling in process... Crawling failed Time Limit:8000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 2795 Appoint description: bupt_admin_13 (2015-07-28) System Crawler (2015-08-18) Description

HDU 2795 &lt;Billboard&gt; &lt;线段树单点更新&gt;

Description At the entrance to the university, there is a huge rectangular billboard of size h*w (h is its height and w is its width). The board is the place where all possible announcements are posted: nearest programming competitions, changes in th

HDU 3308 LCIS (线段树&#183;单点更新&#183;区间合并)

题意  给你一个数组  有更新值和查询两种操作  对于每次查询  输出对应区间的最长连续递增子序列的长度 基础的线段树区间合并  线段树维护三个值  对应区间的LCIS长度(lcis)  对应区间以左端点为起点的LCIS长度(lle)  对应区间以右端点为终点的LCIS长度(lri)  然后用val存储数组对应位置的值  当val[mid + 1] > val[mid] 的时候就要进行区间合并操作了 #include <cstdio> #include <algorithm>

【HDU】1754 I hate it ——线段树 单点更新 区间最值

I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 37448    Accepted Submission(s): 14816 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要

hdu 3308 线段树单点更新 区间合并

http://acm.hdu.edu.cn/showproblem.php?pid=3308 学到两点: 1.以区间端点为开始/结束的最长......似乎在Dp也常用这种思想 2.分类的时候,明确标准逐层分类,思维格式: 条件一成立: { 条件二成立: { } else { } } else { 条件二成立: { } else { } } 上面的这种方式很清晰,如果直接想到那种情况iif(条件一 &条件二)就写,很容易出错而且把自己搞乱,或者情况不全,,,我就因为这WA了几次 3.WA了之后 ,

[HDU] 2795 Billboard [线段树区间求最值]

Billboard Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 11861    Accepted Submission(s): 5223 Problem Description At the entrance to the university, there is a huge rectangular billboard of s

线段树 --- (单点更新、求区间最值、模板题)

A - 敌兵布阵 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营 地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况.由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工 兵营地的人数都有可能发生

HDU 1166(线段树单点更新)

HDU 1166 题意:1-n个堡垒,人数在不断变化,多次查询 l-r人数和: 思路:线段树的单点更新: #include<iostream> #include<cstring> #include<cstdio> #include<string> #include<algorithm> #include<cmath> #include<map> #include<vector> #include<queu