题意: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; }
HDU 2795 Billboard (线段树单点更新)
时间: 2024-10-08 19:55:55