码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 2795 Billboard (RE的可以看一看)

时间:2014-05-15 19:48:31      阅读:348      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   class   code   c   

Problem 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 the dining room menu, and other important information.

On September 1, the billboard was empty. One by one, the announcements started being put on the billboard.

Each announcement is a stripe of paper of unit height. More specifically, the i-th announcement is a rectangle of size 1 * wi.

When someone puts a new announcement on the billboard, she would always choose the topmost possible position for the announcement. Among all possible topmost positions she would always choose the leftmost one.

If there is no valid location for a new announcement, it is not put on the billboard (that‘s why some programming contests have no participants from this university).

Given the sizes of the billboard and the announcements, your task is to find the numbers of rows in which the announcements are placed.
 

Input
There are multiple cases (no more than 40 cases).

The first line of the input file contains three integer numbers, h, w, and n (1 <= h,w <= 10^9; 1 <= n <= 200,000) - the dimensions of the billboard and the number of announcements.

Each of the next n lines contains an integer number wi (1 <= wi <= 10^9) - the width of i-th announcement.
 

Output
For each announcement (in the order they are given in the input file) output one number - the number of the row in which this announcement is placed. Rows are numbered from 1 to h, starting with the top row. If an announcement can‘t be put on the billboard, output "-1" for this announcement.
 

Sample Input
3 5 5 2 4 3 3 3
 

Sample Output
1 2 1 3 -1
 

 最近在学习线段树, 这道题是我搜“线段树练习”时找到的,那么这道题的解法也就是用线段树解决。但是读完题目很容易想到的是暴力,一开始就想到用线段树我觉得不是那么自然。。说一下题意: 一块广告牌长h,宽h,还有m条长度不同的广告,但每条广告的宽度都是1。每次贴广告都往左上贴,能贴上的就输出在第几行,否则输出-1。

我们可以把广告牌假想成一条一条的 , 每条长度为w ,宽度就为1,共有h条,那么区间就是[1~h],可以用线段树维护区间的所有条的剩余的长度  的最大值。(整个题目一大半就在这了) ,叶节点就保存的是每条的剩余。

说一下我写的时候碰到的一些问题,递归左儿子的时候如果把当前的广告插到了左儿子,那么就不必考虑右儿子,用ok标记。

还有就是RE了好多次的一个地方,输入的h可能很大,数组会爆,考虑到如果h超过了m,那么不会存在广告宽度不够用的情况,可以人为的把广告牌改短,改到m,足矣。

但是不可以在建树的时候直接用m,考虑假如m大于h,那么相当于把广告牌加长了,这是不允许的。


#include<stdio.h>
int h,w,m,x,ans,ok,res[800050];
int _max(int a,int b)
{
    return a>b?a:b;
}
void pushup(int o)
{
    res[o]=_max(res[o<<1] , res[o<<1|1]);
}
void build(int o,int l,int r)
{
    res[o]=w;  //优化一点,也可以递归下去到最后再修改然后pushup
    int m=(l+r)>>1;
    if(l == r) return ;
    else {
        build(o<<1,l,m);
        build(o<<1|1,m+1,r);
    }
}
void update(int o,int l,int r)
{
    int m=(l+r)>>1 ;
    if(res[o] >= x) {
        if(l == r) {
            res[o]-=x;
            ans=l;
            ok=1;
        } else {
            ok=0;
            update(o<<1,l,m);
            if(!ok) update(o<<1|1,m+1,r);
            pushup(o);
        }
    }
}
int main()
{
    while(~scanf("%d%d%d",&h,&w,&m)) {
        if(h>m) h=m; // 重点,想了一会才明白,各种RE
        build(1,1,h);
        while (m--) {
            scanf("%d",&x);
            ans=-1;
            update(1,1,h);
            printf("%d\n",ans);
        }
    }
    return 0;
}





HDU 2795 Billboard (RE的可以看一看),布布扣,bubuko.com

HDU 2795 Billboard (RE的可以看一看)

标签:des   style   blog   class   code   c   

原文地址:http://blog.csdn.net/u013923947/article/details/25885079

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!