HDU 2795 Billboard
题意:有一个h*w的广告牌,在这上要贴一些广告,每个广告的高度为一个单位,宽为WI,这样广告牌就可以分成h个层。逐个给出一些广告所占的宽度问你这个广告可以放在第几层(广告尽量靠上靠又)。
题解:线段树。把每一层抽象成一个数,在这些数中找出一个层数最小且大于WI的数,并进行更新(当这一层被一个广告占用一部分时,这个数就减去相应的宽度)。
这里还有个问题:h大到10^9,如果按给定的h建树的话肯定会爆内存!这里注意到n<=20,000,最多占用20,000行,所以只要按如下方式处理就可以了。
if(h>n)h=n;
AC代码:
View Code
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 const int maxn=10000000; 5 int maxnum[maxn]; 6 int max(int a,int b){ 7 return a>b?a:b; 8 } 9 void Build(int l,int r,int pos,int w){ 10 if(l==r){ 11 maxnum[pos]=w; 12 return; 13 } 14 int mid=(l+r)>>1; 15 Build(l,mid,pos*2,w); 16 Build(mid+1,r,pos*2+1,w); 17 maxnum[pos]=w; 18 } 19 void Query(int wi,int l,int r,int pos){ 20 if(maxnum[pos]<wi){ 21 printf("-1\n"); 22 return; 23 } 24 if(l==r){ 25 maxnum[pos]-=wi; 26 printf("%d\n",l); 27 return; 28 } 29 int mid=(l+r)>>1; 30 if(maxnum[pos*2]>=wi)Query(wi,l,mid,pos*2); 31 else Query(wi,mid+1,r,pos*2+1); 32 maxnum[pos]=max(maxnum[pos*2],maxnum[pos*2+1]); 33 } 34 int main() 35 { 36 //freopen("in.txt","r",stdin); 37 int h,w,n,wi; 38 while(scanf("%d %d %d",&h,&w,&n)!=EOF){ 39 if(h>n)h=n; 40 Build(1,h,1,w); 41 while(n--){ 42 scanf("%d",&wi); 43 Query(wi,1,h,1); 44 } 45 } 46 return 0; 47 }
posted on 2012-10-12 21:57 Acmer_Roney 阅读(136) 评论(0) 编辑 收藏 举报