• 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
    ");
    55                 continue;
    56             }else printf("%d
    ", 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
    ");
    41             else printf("%d
    ", query(x, 1, h, 1));
    42         }
    43     }
    44     return 0;
    45 }
    View Code
  • 相关阅读:
    一个纯CSS下拉菜单
    【荐】DIV+CSS仿360buy京东商城导航条
    JS同一个页面布局滑动门和TAB
    很漂亮的蓝色CSS下拉菜单
    用JS已经封装好的滑动门,只需调用就可以用
    set row count
    html块元素与内联元素
    Div的内容自动换行(转载)
    xmlHTTP Status
    FF innerText(转载)
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/6985344.html
Copyright © 2020-2023  润新知