题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2795
题目大意:给你一个h*w的广告版,往上面贴1*wi的广告,求能够贴上且位置最上,最左的行hi,1 <= h,w <= 10^9; 1 <= n <= 200,000
思路:将h分段,树的每个节点表示区间[1,r]内能贴的广告牌的最大宽度,每次通过query来判断能否贴上去,如果可以update
注意:n最多只有200,000,也就是说最多能贴到第200,000行,故要先判断h和n,较小者为要维护的线段树的域。
参考了hh神牛的代码,hh神牛的代码好飘逸orz
代码如下:
1 #include<stdio.h> 2 #define lson l,m,rt<<1 3 #define rson m+1,r,rt<<1|1 4 #define maxn 200010 5 int tree[maxn<<2]; 6 int h,w,n; 7 int max(int a,int b) 8 { 9 return a>b?a:b; 10 } 11 void pushup(int rt) 12 { 13 tree[rt]=max(tree[rt<<1],tree[rt<<1|1]); 14 } 15 void build(int l,int r,int rt) 16 { 17 tree[rt]=w; 18 if(l==r) 19 return ; 20 int m=(l+r)>>1; 21 build(lson); 22 build(rson); 23 } 24 int query(int x,int l,int r,int rt) 25 { 26 if(l==r) 27 { 28 tree[rt]-=x; 29 return l; 30 } 31 int m=(l+r)>>1; 32 int ret; 33 if(tree[rt<<1]>=x) 34 ret=query(x,lson); 35 else 36 ret=query(x,rson); 37 pushup(rt); 38 return ret; 39 } 40 int main() 41 { 42 int x,i; 43 while(scanf("%d%d%d",&h,&w,&n)!=EOF) 44 { 45 if(n<h) 46 h=n; 47 build(1,h,1); 48 for(i=1;i<=n;i++) 49 { 50 scanf("%d",&x); 51 if(tree[1]<x) //不可贴 52 printf("-1\n"); 53 else 54 printf("%d\n",query(x,1,h,1)); 55 } 56 } 57 return 0; 58 }