zoukankan      html  css  js  c++  java
  • HDU2795–Billboard(单点修改&&区间最值)

    题目大意

    给定一个大小为h*w的矩形和n个子矩阵,大小分别为1*w1,1*w2,1*w3,..1*wn。要求你把n个子矩阵按给出顺序依次放置在大矩阵中(如果能够放入的话),使得放置的位置尽量靠顶端,如果有几种情况符合条件的话,选择最靠左的位置放置,要求你输出每个子矩阵放置的位置的行数,如果不能能放置则输出-1

    题解

    线段树的单点修改和区间最值问题,把每一行作为线段树的一个叶子结点,每个叶子结点的初始值都为w。在进行查询的时候,如果左边的最大值大于等于子矩阵的大小就对左子树进行递归查询,否则的话只能在右子树进行查询,找到符合要求的叶子结点,对其进行修改并返回它的行数

    代码:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define lson l, m , s << 1
    #define rson m + 1 , r , s << 1 | 1
    #define MAXN 200005
    using namespace std;
    int w;
    int maxv[MAXN<<2];
    void PushUP(int s)
    {
        maxv[s] = max(maxv[s<<1] , maxv[s<<1|1]);
    }
    void build(int l,int r,int s)
    {
        if(l==r)
        {
            maxv[s]=w;
            return;
        }
        int m=(l+r)>>1;
        build(lson);
        build(rson);
        PushUP(s);
    }
    int query(int p,int l,int r,int s)
    {
        if(l==r)
        {
            maxv[s]-=p;
            return l;
        }
        int m=(l+r)>>1,ans;
        if(maxv[s<<1]>=p)
        ans=query(p,lson);
        else
        ans=query(p,rson);
        PushUP(s);
        return ans;
    }
    int main(void)
    {
        int h,n,k,i;
        while(scanf("%d%d%d",&h,&w,&n)!=EOF)
        {
            if(h>n) h=n;
            build(1,h,1);
            for(i=1; i<=n; i++)
            {
                scanf("%d",&k);
                if(k>maxv[1])
                    printf("-1\n");
                else
                    printf("%d\n",query(k,1,h,1));
            }
        }
        return 0;
    }
  • 相关阅读:
    学python走过的坑 二 element与elements的却别
    Python 进度条显示
    学python走过的坑一 类的实例化
    shell打印 菱形
    shell打印 倒等腰三角形
    互联网协议入门
    shell应用之批量添加用户实例
    Centos7不修改默认交换分区下添加交换分区
    shell中处理用户输入
    sed命令的介绍
  • 原文地址:https://www.cnblogs.com/zjbztianya/p/3076490.html
Copyright © 2011-2022 走看看