HDU 2795 单点更新,区间优先查找(想法)

Billboard

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

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

Author

[email protected]

Source

HDOJ 2009 Summer Exercise(5)

题目意思:

一个h*w的木板,要在在上面贴n张报纸,每个报纸都是1*w[i]矩形,优先贴在木板的上方和左方,报纸之间不能重叠,若能贴输出所贴位置的h(从上到下1-h),否则输出-1。

思路:

暴力肯定超时,需要转换一下思维,若把木板旋转90度呢?问题就变成:给一h*w的矩形,优先往最左边贴报纸,其次往最左面的下边贴报纸。很明显是线段树嘛,维护横着每个单位最小的高度即可。说着不是太好说,看代码吧,代码是最好的解题报告。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <vector>
 6 #include <queue>
 7 #include <cmath>
 8 #include <set>
 9 using namespace std;
10
11 #define N 200005
12 #define ll root<<1
13 #define rr root<<1|1
14 #define mid (a[root].l+a[root].r)/2
15
16
17 int max(int x,int y){return x>y?x:y;}
18 int min(int x,int y){return x<y?x:y;}
19 int abs(int x,int y){return x<0?-x:x;}
20
21 int n;
22 int b[N];
23 int h, w;
24 int ans[N];
25
26 struct node{
27     int l, r, minw;
28 }a[N*4];
29
30 void build(int l,int r,int root){
31     a[root].l=l;
32     a[root].r=r;
33     a[root].minw=0;
34     if(l==r) return;
35     build(l,mid,ll);
36     build(mid+1,r,rr);
37 }
38 int flag;
39
40 void solve(int id,int root){
41     if(b[id]+a[root].minw>w) return;  //若这个区间最小的高度+要贴报纸的高度大于木板的高度则不能贴
42     if(a[root].l==a[root].r){
43         ans[id]=a[root].l;
44         a[root].minw+=b[id];
45         flag=1;
46         return ;
47     }
48     if(b[id]+a[ll].minw<=w) solve(id,ll);  //优先贴最左边
49     else solve(id,rr);
50     a[root].minw=min(a[ll].minw,a[rr].minw);//向上更新
51 }
52
53 main()
54 {
55     int i, j, k;
56     while(scanf("%d %d %d",&h,&w,&n)==3){
57         for(i=1;i<=n;i++) scanf("%d",&b[i]);
58         build(1,min(n,h),1);
59         for(i=1;i<=n;i++){
60             if(b[i]>w){          //若b[i]>w,显然不能贴
61                 ans[i]=-1;continue;
62             }
63             flag=0;
64             solve(i,1);
65             if(!flag) ans[i]=-1; //若不能贴
66         }
67         for(i=1;i<=n;i++) printf("%d\n",ans[i]);
68     }
69 }
时间: 2024-10-12 19:29:41

HDU 2795 单点更新,区间优先查找(想法)的相关文章

【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 1166 敌兵布阵(线段树之 单点更新+区间求和)

敌兵布阵                                                                             Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵

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

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

LightOJ 1112 Curious Robin Hood (单点更新+区间求和)

http://lightoj.com/volume_showproblem.php?problem=1112 题目大意: 1 i        将第i个数值输出,并将第i个值清0 2 i v     将第i个数值加v 3 i j      输出从i到j的数值和 简单的单点更新+区间求和,代码很简单的模板 但此题有一个神坑的地方当操作为1是输出第i个数值不是直接输出,而是通过查找输出(太坑了...) #include<stdio.h> #include<string.h> #incl

poj 1195 单点更新 区间求和

Mobile phones Time Limit: 5000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java class name: Main [Submit] [Status] [Discuss] Description Suppose that the fourth generation mobile phone base stations in the Tampere area operate a

light oj 1348 树链剖分(单点更新区间求值)

http://lightoj.com/volume_showproblem.php?problem=1348 Finally the Great Magical Lamp was in Aladdin's hand. Now he wanted to return home. But he didn't want to take any help from the Genie because he thought that it might be another adventure for hi

FZU2082 树链剖分(单点更新区间求值)

http://acm.fzu.edu.cn/problem.php?pid=2082  Problem Description 有n座城市,由n-1条路相连通,使得任意两座城市之间可达.每条路有过路费,要交过路费才能通过.每条路的过路费经常会更新,现问你,当前情况下,从城市a到城市b最少要花多少过路费.  Input 有多组样例,每组样例第一行输入两个正整数n,m(2 <= n<=50000,1<=m <= 50000),接下来n-1行,每行3个正整数a b c,(1 <=

HYSBZ 1036 树链剖分(单点更新区间求和求最大值)

http://www.lydsy.com/JudgeOnline/problem.php?id=1036 Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身 Input 输入

hdu2795(线段树单点更新&amp;区间最值)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2795 题意:有一个 h * w 的板子,要在上面贴 n 条 1 * x 的广告,在贴第 i 条广告时要尽量将其靠上贴,并输出其最上能贴在哪个位置: 思路:可以将每行剩余空间大小存储到一个数组中,那么对于当前 1 * x 的广告,只需找到所有剩余空间大于的 x 的行中位置最小的即可: 不过本题数据量为 2e5,直接暴力因该会 tle.可以用个线段树维护一下区间最大值,然后查询时对线段树二分即可: 代码