HDU 2795 Billboard(线段树)

题目大意是:给一个h高w宽的广告牌,和n个高为1长度为Wi的广告,广告总是选择最高位置的最左边。求每次广告放的行数是多少。

 

用线段树可以先判断高度是否大于n个广告,大于的话没有必要建立h高的广告牌。并使每个区间的值都为w,每次查询成功时减下Wi就行了,具体代码如下:

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #define lson l, m, rt<<1
 4 #define rson m+1, r, rt<<1|1
 5 
 6 using namespace std;
 7 const int maxn = 2e5+10;
 8 int n, h, w;
 9 int MAX[maxn<<2];
10 void PushUP(int rt){
11     MAX[rt] = max(MAX[rt<<1], MAX[rt<<1|1]);
12 }
13 
14 void build(int l, int r, int rt){//建立线段树
15     MAX[rt] = w;
16     if(l == r)return;
17     int m = (l + r) >> 1;
18     build(lson);
19     build(rson);
20 }
21 int query(int q, int l, int r, int rt){
22     if(l == r){
23         MAX[rt] -= q;//每次查询时减下q
24         return l;
25     }
26     int m = (l + r) >> 1;
27     int ret = (MAX[rt<<1] >= q)?query(q, lson):query(q, rson);//求出满足条件的最左边区间
28     PushUP(rt);
29     return ret;
30 }
31 
32 int main()
33 {
34     while(~scanf("%d%d%d",&h,&w,&n)){
35         if(h > n) h = n;//这样建立的区间更少些
36         build(1, h, 1);
37         while(n--){
38             int x;
39             scanf("%d",&x);
40             if(MAX[1] < x) printf("-1\n");
41             else printf("%d\n",query(x, 1, h, 1));
42         }
43     }
44     return 0;
45 }

 

posted @ 2017-03-14 13:31  starry_sky  阅读(117)  评论(0编辑  收藏  举报