• HDU 2795 Billboard (线段树单点更新 && 求区间最值位置)


    题意 : 有一块 h * w 的公告板,现在往上面贴 n 张长恒为 1 宽为 wi 的公告,每次贴的地方都是尽量靠左靠上,问你每一张公告将被贴在1~h的哪一行?按照输入顺序给出。

    分析 : 这道题说明了每一次贴都尽量选择靠上靠左的位置,那既然这样,我们以1~h建立线段树,给每一个叶子节点赋值初值 w 表示当前行最大能够容纳宽度为 w 的公告纸,那么对于某一输入 wi 只要在线段树的尽量靠左的区间找出能够容纳这张公告的位置(即叶子节点)然后减去 wi 即可,需要对query()函数进行一点改造,将其返回的是叶子节点,判断递归的条件也由当前的 wi 决定。

    #include <cstdio>
    #include <algorithm>
    #include <string.h>
    using namespace std;
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    const int maxn = 222222;
    int maxv[maxn<<2];
    int h, w, n;
    void PushUP(int rt) { maxv[rt] = max(maxv[rt<<1] , maxv[rt<<1|1]); }
    
    void build(int l,int r,int rt) {
        maxv[rt] = w;
        if (l == r) return ;
        int m = l + ((r - l)>>1);
        build(lson);
        build(rson);
    }
    
    void update(int p,int sc,int l,int r,int rt) {
        if (l == r) {
            maxv[rt] += sc;
            return ;
        }
        int m = l + ((r - l)>>1);
        if (p <= m) update(p , sc , lson);
        else update(p , sc , rson);
        PushUP(rt);
    }
    int val;
    int query(int l,int r,int rt) {
        if(l == r) return l;
        int m = (l + r) >> 1;
        int ret = 0;
        if(maxv[rt<<1] >= val) ret = query(lson);///先判断左孩子,使得贴的位置会尽量靠上
        else ret = query(rson);
        return ret;
    }
    
    int main(void)
    {
        while(~scanf("%d %d %d", &h, &w, &n)){
            if(h > n) h = n;///这里需要注意 h 最大是 1e9,但是很明显公告占行数最大只会到 n 这么大
            build(1, h, 1);///建树,一开始每一个节点的最大值都是 w
            for(int i=1; i<=n; i++){
                scanf("%d", &val);///输入每张公告的长度
                if(maxv[1] < val) puts("-1");///如果总区间中含有的最大空间都无法容纳当前公告,输出 -1
                else{
                    int pos = query(1, h, 1);///查找最大值的位置,注意返回的是位置
                    update(pos, -val, 1, h, 1);///将这个位置减去 wi
                    printf("%d
    ", pos);///输出对应的位置
                }
            }
        }
        return 0;
    }
    View Code

    瞎 : 这道题要求返回的不是最大值,而是最大值的位置,如果硬套线段树模版肯定是不行的,需要对模版有很清楚的认识,不然很多变形题目就能难倒自己!

  • 相关阅读:
    oracle实现自增id
    一些.NET 项目中经常使用的类库
    文件读取是判断是否读取到末尾
    文件操作
    第一个html文件
    HTML标签(持续更新)
    配置tomcat
    判断一个String中是否有指定字符或字符串
    去掉字符串中的某个字符
    把一个activity作为弹窗
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/7390265.html
Copyright © 2020-2023  润新知