习题:公告板

版权声明:转载记得标明出处哦~ https://blog.csdn.net/weixin_43890047/article/details/88774442

题目:公告板

思路:

将公告板的高度看做一个区间,区间每个点的长度为wi。
构建维护区间最长长度的线段树,进行求解。
优先从上到下贴,即优先从最左侧区间开始黏贴。

※注意!要看是什么在决定区间长度的最大值,而这道题是n,不是h!

代码:
#include<bits/stdc++.h>
using namespace std;
const int MAX_N = 200050;
int c[4*MAX_N] = {0};

void up(int p)
{
    c[p] = max(c[2*p],c[2*p+1]);
}

int modify(int p,int l,int r,int v)
{
    if(l==r){
        c[p]-=v;
        return l;
    }
    if(c[p]<v){
        return -1;
    }
    int mid = (l+r)/2;
    int res = 0;
    if(c[2*p]>=v){
        res = modify(2*p,l,mid,v);
    }
    else if(c[2*p+1]>=v){///这里一定是else if,这有前后优先级,优先放前
        res = modify(2*p+1,mid+1,r,v);
    }

    up(p);
    return res; ///整个函数最重要的是返回值,在递归最外(结果递归)的res代表的就是函数的返回值
}

int main()
{
    int h,w,n;
    scanf("%d%d%d",&h,&w,&n);
    for(int i=0;i<4*MAX_N;i++){     ///先将区间的最大值全部设为w,因为初始值即为w,最大值也为w
        c[i] = w;
    }
    for(int i=0;i<n;i++){
        int length;
        scanf("%d",&length);
        if(length>w) {printf("-1");continue;}
        printf("%d\n",modify(1,1,h,length));      ///可以简单地理解,在修改的时候已经完成信息的输出了,那这时候就不需要查询了
        ///故没有query函数。这时候modify的返回类型是int
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43890047/article/details/88774442