HDU 2795 Billboard 线段树

来源:互联网 发布:淘宝博娱乐nb88.com 编辑:程序博客网 时间:2024/06/03 11:37

Billboard

Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 12333    Accepted Submission(s): 5408


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 524333
 

Sample Output
1213-1
 

Author
hhanger@zju
 

Source
HDOJ 2009 Summer Exercise(5)


题意:

校门口有高度为h,宽为w的广告牌子,同学可以网上贴广告,数据给你说有n个广告纸,高度为1,宽度告诉你,问问你它能贴在第几行,h会分成高度为1,宽度为w的h段,标号从上到下是1到h,贴广告的时候遵循最靠上,最靠左的原则。求这个原则下这个广告纸能贴在哪一行。

分析:看了分类才知道是线段树,猛一想还以为来个二维的线段树呢,后来想了想,一维的就可以了,题目给出数据h是1到10^9,很明显,开10^9 * 4的内存是开不开的,后来想到了离散化,貌似这个题用不到离散化,因为最多n组数据,也就是说如果宽度都为w的话最多也就n段,也就是说,线段树最大区间是1到n。线段树维护某个区间的最大值,如果某个区间的最大值都比要贴的广告的宽度要窄的话,就不用去那个区间找了,这也是一个优化吧。。。。。


#include <stdio.h>#include <string.h>#define max(a,b) (a) > (b) ? (a) : (b)const int inf = 999999999;int d[200010 << 2];//n的最大值的4倍就行了int mn;//记录最终答案bool flag;//标记是否找到最终答案void build(int s,int t,int w,int step)//建树{    d[step] = w;//都初始化为w    if(s >= t)        return ;    int mid = (s + t) >> 1;    build(s,mid,w,step << 1);    build(mid + 1,t,w,step << 1 | 1);}void upd(int s,int t,int sr,int step){    if(s >= t)//找到s == t后    {        if(mn > s && d[step] >= sr)//当当前行比找到的行数要小并且当前行的宽度足以贴上这个广告纸时        {            flag = true;//找到答案            mn = s;//记录最小行            d[step] -= sr;//减掉已经覆盖的长度        }        return ;    }    if(d[step] >= sr && !flag)//当前区间最大值>当前广告纸宽度并且未找到答案时    {        int mid = (s + t) >> 1;        upd(s,mid,sr,step << 1);//优先找左边,因为通一个节点左边表示的行要小有右边        if(flag)//如果左边已经更新mn值,没必要找右边了        {            d[step] = max(d[step << 1],d[step << 1 | 1]);//回溯记录最大值            return ;        }        upd(mid + 1,t,sr,step << 1 | 1);//找右边    }    d[step] = max(d[step << 1],d[step << 1 | 1]);//维护最大值}int main(){    int h,w,n,sr;    while(~scanf("%d%d%d",&h,&w,&n))    {        if(h > n)            h = n;//h和n取最小,1到h就是边界了        build(1,h,w,1);        for(int i = 0; i < n; i++)        {            mn = inf;//初始化最终答案为最大            flag = false;//默认未找到答案            scanf("%d",&sr);            if(d[1] < sr)//如果d[1] < sr,那就不用找了,贴不上了            {                printf("-1\n");                continue;            }            upd(1,h,sr,1);            printf("%d\n",mn);        }    }    return 0;}






0 0
原创粉丝点击