hdu2795 Billboard ——线段树入门题

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

题目大意:

  高度为h,长度为w的板子,贴n个海报,每个海报的高度都为1,长度由n个整数给出。贴海报的原则是,从高到低,优先选高的,从左到右,优先选右边的位置。起初每个海报在板子上所在的行数。

题目思路:

  建立一棵叶子节点有h个的线段树,每个节点代表这个区间内的最大值,最开始,叶子节点都是w。然后每插入一个值就插入到叶子节点,输出叶子节点的值,然后更新父节点。

  这道题目的难点是,要想到建立线段树,把模型抽象出来。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cctype>
 6 #include <stack>
 7 #include <queue>
 8 #include <map>
 9 #include <set>
10 #include <vector>
11 #include <cmath>
12 #include <algorithm>
13 #define lson l, m, rt<<1
14 #define rson m+1, r, rt<<1|1
15 using namespace std;
16 typedef long long int LL;
17 const int MAXN =  0x3f3f3f3f;
18 const int  MIN =  -0x3f3f3f3f;
19 const double eps = 1e-9;
20 const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1},
21   {1,1},{1,-1},{-1,-1}};
22 const int MAX = 200000+10;
23 int a[MAX<<2], n, h, w, b[MAX];
24 void pushup(int rt)
25 {
26   a[rt] = max(a[rt<<1], a[rt<<1|1]);
27 }
28 void build(int l, int r, int rt)
29 {
30   if (l == r) { a[rt] = w; return; }
31   int m = (l + r) >> 1;
32   build(lson); build(rson); pushup(rt);
33 }
34 void update(int p, int k, int l, int r, int rt)
35 {
36   if (l == r) { a[rt] -= k; return; }
37   int m = (l + r) >> 1;
38   if (p <= m) update(p, k, lson);
39   else update(p, k, rson);
40   pushup(rt);
41 }
42 int query(int k, int l, int r, int rt)
43 {
44   if (l == r) { return l; }
45   int m = (l + r) >> 1, ret = 0;
46   /*
47   if (a[rt<<1] >= k) ret = query(k, lson);
48   else ret = query(k, rson);
49   */
50   if (a[rt] >= k) {
51     if (a[rt<<1] >= k) ret = query(k, lson);
52     else ret = query(k, rson);
53   }
54   else return 0;
55 
56   return ret;
57 }
58 int main(void){
59 #ifndef ONLINE_JUDGE
60   freopen("hdu2795.in", "r", stdin);
61 #endif
62   int i, j, k;
63   while (~scanf("%d%d%d", &h, &w, &n)){
64     if (h > n) h = n;
65     build(1, h, 1);
66     for (i = 0; i < n; ++i) {
67       scanf("%d", b + i);
68       if (a[1] < b[i]) { printf("-1\n"); continue; }
69       k = query(b[i], 1, h, 1);
70       printf("%d\n", k); update(k, b[i], 1, h, 1);
71     }
72   }
73 
74   return 0;
75 }

  注释掉的两行代码也是可以的,只不过是以前抄的NOTONLYSUCCESS的。其实思想是一样的。还是谢谢HH神牛,线段树就是看着他的博客学的。

posted on 2013-04-24 09:30  aries__liu  阅读(162)  评论(0编辑  收藏  举报