线段树---HDU2795Billboard

这道题跟第二个题差不多,求单点的最大值。

题目大意:有个高和宽分别为h, w的广告牌, 这个广告牌分成高为 1 的长条, 每条分别能贴长度为wi长度的广告, 输入的n为广告的条数,广告优先贴在最上边和最左边, 让输出每个广告能贴的层数,如果贴不下了,就输出-1

主要思路:

1. 建立线段树,初始化每个节点的值为w, 因为这个每条的宽

2. 读入点,并更新线段树并且还要输出第几层来

代码如下:

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 using namespace std;
 5 
 6 const int MAX = 200500 * 4;
 7 
 8 int sum[MAX];
 9 int h, w, n;
10 
11 void pushUp(int root)
12 {
13     sum[root] = max(sum[root * 2], sum[root * 2 + 1]);
14 }
15 
16 void buildTree(int root, int left, int right)
17 {
18     sum[root] = w;//初始化为w 
19     if(left == right)
20         return;
21     int mid = (left + right) / 2;
22     buildTree(root * 2, left, mid);
23     buildTree(root * 2 + 1, mid + 1, right);
24 }
25 //查询并更新 
26 int query(int root, int size, int left, int right)
27 {
28     if(left == right)
29     {
30         sum[root] -= size;//找到就更新 
31         return left;
32     }
33     int mid = (left + right) / 2;
34     int res;
35     if (sum[root * 2] >= size) 
36         res = query(root * 2, size, left, mid);
37     else
38         res = query(root * 2 + 1, size, mid + 1, right);
39     pushUp(root);//把它上面有关的点调整 
40     return res;
41 } 
42 
43 int main()
44 {
45     int x;
46     while(~scanf("%d %d %d", &h, &w, &n))
47     {
48         if(h > n)
49             h = n;
50         buildTree(1, 1, h);
51         for(int i = 0; i < n; i++)
52         {
53                 scanf("%d", &x);
54             if(sum[1] < x)//如果根节点都小于了,下面的肯定不能有大于x的了 
55                 printf("-1\n");
56             else
57                 printf("%d\n", query(1, x, 1, h));    
58         }
59     }
60     
61     return 0;
62 }

 

posted @ 2014-10-29 18:39  Howe_Young  阅读(383)  评论(0编辑  收藏  举报