题意: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;
}