hdu2795(线段树单点更新&区间最值)

Posted ygeloutingyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu2795(线段树单点更新&区间最值)相关的知识,希望对你有一定的参考价值。

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

 

题意:有一个 h * w 的板子,要在上面贴 n 条 1 * x 的广告,在贴第 i 条广告时要尽量将其靠上贴,并输出其最上能贴在哪个位置;

 

思路:可以将每行剩余空间大小存储到一个数组中,那么对于当前 1 * x 的广告,只需找到所有剩余空间大于的 x 的行中位置最小的即可;

不过本题数据量为 2e5,直接暴力因该会 tle.可以用个线段树维护一下区间最大值,然后查询时对线段树二分即可;

 

代码:

技术分享
 1 #include <iostream>
 2 #include <stdio.h>
 3 #define lson l, mid, rt << 1
 4 #define rson mid + 1, r, rt << 1 | 1
 5 using namespace std;
 6 
 7 const int MAXN = 2e5 + 10;
 8 int Max[MAXN << 2], h, w, n;
 9 
10 int max(int a, int b){
11     return a > b ? a : b;
12 }
13 
14 void push_up(int rt){
15     Max[rt] = max(Max[rt << 1], Max[rt << 1 | 1]);
16 }
17 
18 void build(int l, int r, int rt){//建树
19     Max[rt] = w;
20     if(l == r) return;
21     int mid = (l + r) >> 1;
22     build(lson);
23     build(rson);
24 }
25 
26 void update(int p, int x, int l, int r, int rt){//单点更新
27     if(l == r){
28         Max[rt] -= x;
29         return;
30     }
31     int mid = (l + r) >> 1;
32     if(p <= mid) update(p, x, lson);
33     else update(p, x, rson);
34     push_up(rt);
35 }
36 
37 int query(int x, int l, int r, int rt){//查询
38      if(l == r) return l;
39      int mid = (l + r) >> 1;
40      int ans = 0;
41      if(Max[rt << 1] >= x) ans = query(x, lson);
42      else ans = query(x, rson);
43      return ans;
44 }
45 
46 int main(void){
47     while(~scanf("%d%d%d", &h, &w, &n)){
48         if(h > n) h = n;
49         build(1, h, 1);
50         while(n--){
51             int x, cnt;
52             scanf("%d", &x);
53             if(Max[1] < x){
54                 printf("-1\n");
55                 continue;
56             }else printf("%d\n", cnt = query(x, 1, h, 1));
57             update(cnt, x, 1, h, 1);
58         }
59     }
60     return 0;
61 }
View Code

 

其实这个代码中的更新的路径和查询的路径是一样的,可以优化一下,将更新写进查询里面去;

 

优化代码:

技术分享
 1 #include <iostream>
 2 #include <stdio.h>
 3 #define lson l, mid, rt << 1
 4 #define rson mid + 1, r, rt << 1 | 1
 5 using namespace std;
 6 
 7 const int MAXN = 2e5 + 10;
 8 int Max[MAXN << 2], h, w, n;
 9 
10 int push_up(int rt){
11     Max[rt] = max(Max[rt << 1], Max[rt << 1 | 1]);
12 }
13 
14 void build(int l, int r, int rt){
15     Max[rt] = w;
16     if(l == r) return;
17     int mid = (l + r) >> 1;
18     build(lson);
19     build(rson);
20 }
21 
22 int query(int x, int l, int r, int rt){
23     if(l == r){
24         Max[rt] -= x;
25         return l;
26     }
27     int mid = (l + r) >> 1;
28     int cnt = (Max[rt << 1] >= x) ? query(x, lson) : query(x, rson);
29     push_up(rt);
30     return cnt;
31 }
32 
33 int main(void){
34     while(~scanf("%d%d%d", &h, &w, &n)){
35         if(h > n) h = n;
36         build(1, h, 1);
37         while(n--){
38             int x;
39             scanf("%d", &x);
40             if(Max[1] < x) printf("-1\n");
41             else printf("%d\n", query(x, 1, h, 1));
42         }
43     }
44     return 0;
45 }
View Code

 

以上是关于hdu2795(线段树单点更新&区间最值)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 1754 I Hate It(线段树单点更新区间查询最值)

HDU 1754 I Hate It(线段树之单点更新,区间最值)

hdu 1754 I Hate It(线段树之 单点更新+区间最值)

HDU 1754 I Hate It(线段树之单点更新 区间最值查询)

HDU 1754区间最值 & SPLAY

51nod1287(二分/线段树区间最值&单点更新)