线段树单点更新 hdu 2795 Billboard

题目链接: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 }
View Code

 

posted on 2013-05-23 20:44  jumpingfrog0  阅读(146)  评论(0编辑  收藏  举报

导航