线段树---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 }