题目:公告板
思路:
将公告板的高度看做一个区间,区间每个点的长度为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;
}