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

posted @ 2012-10-11 13:03  Griselda.  阅读(549)  评论(0编辑  收藏  举报