线段树单点更新 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

 

你可能感兴趣的:(HDU)