线段树-hdu2795 Billboard(贴海报)

hdu2795 Billboard
题意:h*w的木板,放进一些1*L的物品,求每次放空间能容纳且最上边的位子
思路:每次找到最大值的位子,然后减去L

线段树功能:query:区间求最大值的位子(直接把update的操作在query里做了) 

题意:有一块长方形h*w的广告板,往上面贴广告,然后给n个1*wi的广告,要求把广告贴上去,如果前面的行可以贴,就要贴前面的并且要靠左贴,前面的贴不下就贴在下面,

广告的高度是wi,如果能贴在上面输出最小的高度,如果不能就输出-1。

解题思路:如果以行数为区间,建立线段树,他给的h有10^9次,是创不了10^9这么大的数组的。然而我们知道给定N个广告,应为宽度一定,那么最高也不会超过N;所以我们就建 n个节点的线段树 而n<=20W

 样例:

Sample Input
3 5 5 2 4 3 3 3
 

Sample Output
1 2 1 3 -1
 

AC代码

#include <cstdio>  
#define lson l , m , rt << 1  
#define rson m + 1 , r , rt << 1 | 1  
const int maxn = 200005; 
int h,w,n;
struct Tree{  
    int value;  
}tree[maxn<<2];  
  
int max(int va,int vb){
	return va>vb?va:vb;
}

void PushUP(int rt) {  
    tree[rt].value = max(  tree[rt<<1].value,   tree[rt<<1|1].value  );
}  
void build(int l,int r,int rt) { 
	tree[rt].value=w; //初始化
    if (l == r) {  
        return ;  
    }  
    int m = (l + r) >> 1;  
    build(lson);  
    build(rson);  
    //PushUP(rt);  这题初始化w 没必要这步了
}  
/*
void update(int x,int p,int l,int r,int rt) {//p表示要进行操作的人是第几个  
    if (l == r) {   
        tree[rt].value -=x;  
        return ;  
    }  
    int m = (l + r) >> 1;  
    if (p <= m) update(x , p , lson);  
    else update(x , p , rson);  
    PushUP(rt);  //这步需要,
}  
*/
int query(int x,int l,int r,int rt) {  
    if (l == r) {  
		//update(x,r,1,h,1);
		tree[rt].value -= x;
		return r;
        
    }  
    int m = (l + r) >> 1;  
	int ret = 0 ;
    if (x <= tree[rt<<1].value) ret= query(x , lson);  //先取左
    else  ret= query(x , rson);  

	PushUP(rt); //往上更新
    return ret;  
}  
int main() {
	while (~scanf("%d%d%d",&h,&w,&n)) {
		if (h > n) h = n; //比较重要的一步
		build(1 , h , 1);
		while (n --) {
			int x;
			scanf("%d",&x);
			if (tree[1].value<x) printf("-1
");
			else printf("%d
",query(x , 1 , h , 1));
		}
	}
	return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

today lazy . tomorrow die .
原文地址:https://www.cnblogs.com/france/p/4808775.html