Hdu 2795 线段树 区间最大值的位置.cpp

题意:

  一个board的面积是h*w..在上面贴一些announcement..

  给出告示的宽度ww..可知告示的面积为1*ww..

  问告示是否可以贴上去..可以就输出在board的第几行..不可以就输出-1

 

思路:

  以min(h, n)为长度建一棵树..

  然后每一个的叶子的长度为w..

  找出所有叶子中最大的那个..把announcement贴上去..

  用ma数组存当前区间最大值..

 

Tips:

  查询和更新可以一起写..但是我分开写了..

  然后还有一个要注意的是..树的最大宽度为min(h, n)
  比较的时候是和左右节点大小比..

  ※ 所以modify的时候判断条件也应该是if(x > ma[rt<<1])..

  

 

Code:

View Code
 1 #include <stdio.h>

 2 #include <cstring>

 3 #include <algorithm>

 4 using namespace std;

 5 

 6 const int MAXN = 200010;

 7 int ma[MAXN<<2];

 8 int h, w, n;

 9 

10 void pushup(int rt)

11 {

12     ma[rt] = max(ma[rt<<1], ma[rt<<1|1]);

13 }

14 

15 void creat(int l, int r, int rt)

16 {

17     ma[rt] = w;

18     if(l == r)

19         return;

20     int mid = (l+r)>>1;

21     creat(l, mid, rt<<1);

22     creat(mid+1, r, rt<<1|1);

23 }

24 

25 void modify(int p, int ww, int l, int r, int rt)

26 {

27     if(l == r) {

28         ma[rt] += ww;

29         return;

30     }

31     int mid = (l+r)>>1;

32     if(p <= mid) modify(p, ww, l, mid, rt<<1);

33     else modify(p, ww, mid+1, r, rt<<1|1);

34     pushup(rt);

35 }

36 

37 int query(int x, int L, int R, int rt)

38 {

39     if(L == R) {

40         return L;

41     }

42     int mid = (L+R)>>1;

43     int res = 0;

44     if(x <= ma[rt<<1]) query(x, L, mid, rt<<1);

45     else query(x, mid+1, R, rt<<1|1);

46 }

47 

48 int main()

49 {

50     int i, j;

51     int ww;

52     int ans;

53     while(scanf("%d %d %d", &h, &w, &n) != EOF)

54     {

55         if(h > n) h = n;

56         creat(1, h, 1);

57 

58         for(i = 0; i < n; ++i) {

59             scanf("%d", &ww);

60             if(ww > ma[1]) puts("-1");

61             else {

62                 ans = query(ww, 1, h, 1);

63                 printf("%d\n", ans);

64                 modify(ans, -ww, 1, h, 1);

65             }

66 

67         }

68     }

69     return 0;

70 }

 

 

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2795

你可能感兴趣的:(HDU)