HDU 2795 线段树(转变思维方能改变世界)

Billboard

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

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

题目意思:

输入3个数字h,w,n

在宽为h,长为w的木板上贴n张海报,每张海报的宽为1,长度不确定。

以下n行为每次贴的海报的长。

贴海报时必须优先贴木板左上方(海报不能重叠),若贴上了,输出该海报贴的位置的行(行即为木板的宽上面的数字,宽的最上面为1,从上往下依次增加1),反之输出-1。

思路:
若按平常思维,就是每次贴海报就从第一行开始,看是否能贴,若能则贴,不能则判断下一行,直到最后一行,若实在贴不下输出-1.

代码太复杂了,实现难度也太大,那怎么办呢,就需要打破常规,转换一下思维方式。

若把木板转一下,使得原来的长变成宽,原来的宽变成长。那么贴海报不就成了盖楼了吗,若能贴,则这一列的高度h=h+海报的长度,否则则判断下一列。把转置后得木板的宽当作区间段,这不就是单点增加么,代码就好些的多了,贴海报的过程即为先序遍历了。细节:输入的木板的宽和列都太大,建树需要离散化吗?一般来说需要离散化,但本题说贴海报的时候优先贴木板左上方,给的操作次数n可以当作列数,因为若m张海报全部贴上,最多也只能贴m列。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 using namespace std;
 6 #define N 200005
 7
 8 struct node{
 9     int l, r;
10     int h;
11 }a[N*4];
12
13 int h, w;
14
15 void build(int left,int right,int root){
16     a[root].l=left;
17     a[root].r=right;
18     a[root].h=0;
19     if(left==right) return ;
20     int mid=(left+right)/2;
21     build(left,mid,root*2);
22     build(mid+1,right,root*2+1);
23 }
24
25 int update(int height,int root){
26     if(a[root].h+height>w) return -1;
27     if(a[root].l==a[root].r){
28         a[root].h+=height;
29         return a[root].l;
30     }
31     int t=update(height,root*2);
32     if(t==-1) t=update(height,root*2+1);
33     if(t!=-1) a[root].h=min(a[root*2].h,a[root*2+1].h);
34     return t;
35 }
36 main()
37 {
38     int n;
39     int i, j, k, ww;
40     while(scanf("%d %d %d",&h,&w,&n)==3){
41         if(h>200000) h=200000;
42         build(1,h,1);
43         while(n--){
44             scanf("%d",&ww);
45             printf("%d\n",update(ww,1));
46
47         }
48     }
49 }

HDU 2795 线段树(转变思维方能改变世界)

时间: 2024-12-10 04:37:36

HDU 2795 线段树(转变思维方能改变世界)的相关文章

hdu 2795 线段树--点更新

http://acm.hdu.edu.cn/showproblem.php?pid=2795 多校的第一场和第三场都出现了线段树,比赛期间没做,,这两天先做几道热身下,然后31号之前把那两道多校的线段树都搞了,这是一道热身题 关键是建模: 首先一定看清楚题目构造的场景,看有什么特点--------会发现,如果尽量往左上放置的话,那么由于 the i-th announcement is a rectangle of size 1 * wi.,完全可以对h建立线段树,表示一行,结点里的l,r就表示

hdu 2795 线段树(二维问题一维化)

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

HDU 2795 线段树单点更新

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

hdu 5792 线段树+离散化+思维

题目大意: Given a sequence A with length n,count how many quadruple (a,b,c,d) satisfies: a≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Ac>Ada≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Ac>Ad. A1,A2?AnA1,A2?An.  1≤n≤500001≤n≤50000  0≤Ai≤1e9 基本思路: 最朴素的思想就是算出所有顺序对所有逆序对

hdu 2795 线段树(纵向)

注意h的范围和n的范围,纵向建立线段树 题意:h*w的木板,放进一些1*L的物品,求每次放空间能容纳且最上边的位子思路:每次找到最大值的位子,然后减去L线段树功能:query:区间求最大值的位子(直接把update的操作在query里做了)3 5 524333 1213-1 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include&

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

h*w的木板,放进一些1*L的物品,求每次放空间能容纳且最上边的位子. 每次找能放纸条而且是最上面的位置,询问完以后可以同时更新,所以可以把update和query写在同一个函数里. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int maxn = 200000 + 10; 7 8 int _max[maxn <&l

hdu 4893 (多校1007)Wow! Such Sequence!(线段树&amp;二分&amp;思维)

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 352    Accepted Submission(s): 104 Problem Description Recently, Doge got a funny birthday present from his new friend, Prot

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

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

HDU 3308 线段树(区间合并)

LCIS Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3896    Accepted Submission(s): 1766 Problem Description Given n integers.You have two operations:U A B: replace the Ath number by B. (index