首页 > 代码库 > HDU 2795 Billboard (线段树单点更新)

HDU 2795 Billboard (线段树单点更新)



题意:h,w,n:有一个h*w尺寸的木板,n张1*wi的海报,贴海报的位置尽量高,尽量往左,问每张海报贴的高度


看到1 <= h,w <= 10^9; 1 <= n <= 200,000,应该就是线段树了。


关键在怎么建树,这里我们对h进行分割,每个高度都有等长的w,我们从上往下贴,如果当前高度

(在同一高度上l==r)的长度可以满足wi则可以贴,否则继续往下寻找。


#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define M 303
#define inf 0x3fffffff
#define maxn 500000*2

struct Tree
{
	int left,right,num;
}tree[maxn];
int s,h,w,n;
void build_tree(int l,int r,int id)
{
	tree[id].left=l;tree[id].right=r;tree[id].num=w;
	if(l!=r)
	{
		int mid=(l+r)/2;
		build_tree(l,mid,id*2);
		build_tree(mid+1,r,id*2+1);
	}
}
int query(int h,int id)
{
	int l=tree[id].left,r=tree[id].right;
	if(tree[id].right==tree[id].left)//在一个高度上
	{
		tree[id].num-=h;
		return tree[id].left;
	}
	else 
	{
		int pos;
		if(tree[id*2].num>=h) pos=query(h,id*2);
		else pos=query(h,id*2+1);
		tree[id].num=max(tree[id*2].num,tree[id*2+1].num);
		return pos;
	}
}
int main()
{
	while(~scanf("%d%d%d",&h,&w,&n))
	{
		build_tree(1,min(h,200000),1);
		int a;
		for(int i=0;i<n;i++)
		{
			scanf("%d",&a);
			if(tree[1].num<a) printf("-1\n");
			else printf("%d\n",query(a,1));
		}
	}
	return 0;
}