这题以前貌似也做过。。。当时卡住的地方,现在还是卡,因为当时是看了结题报告的。。。噗噗。。
看来,只有自己真的由内而外的想出来才是真的明白啊。。
直接贴代码辣。。。里面有注释
//题意:展板 h*w 一行一行的贴海报,海报高度为1 ,宽度不同,按照规矩从上到下,从左向右贴
// 结果输出每个海报贴在哪一行,如果贴不下,就输出 -1;
//问题: 如何将二维的行列 映射到线段树的一段区间中呢?
// 按照行的数目来建区间 然后sum[]里存的是这一行的剩余容量
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
#define maxn 200005
int h,w,n;
int sum[maxn<<2];
void push_up(int rt)
{
sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);
}
void build(int l,int r,int rt)
{
sum[rt]=w;
if(l==r)
{
return ;
}
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
}
//update可以和 query里 一起进行
//如何找到那个正确的行呢?
int query(int L,int l,int r,int rt)
{
if(l==r)
{
sum[rt]-=L; //找到最底层开始更新
return l;
}
int res=0;
int mid=(l+r)>>1;
if(L<=sum[rt<<1])res=query(L,l,mid,rt<<1);
else res=query(L,mid+1,r,rt<<1|1);
push_up(rt);
return res;
}
int main()
{
//freopen("q.in","r",stdin);
int L,i;
while(scanf("%d%d%d",&h,&w,&n)==3)
{
if(h>n)h=n; //显然可以减少建树的内存 ,本来h的范围很大,还需要离散化数据
build(1,h,1); // 但是酱紫 就不需要了 因为n很小 h 是骗人的啊。。。
// cout<<sum[1]<<endl;
for(i=0;i<n;i++)
{
scanf("%d",&L);
if(L>sum[1])
{
printf("-1\n");
}
else printf("%d\n",query(L,1,h,1)); //cout 超时 噗噗。。。
}
}
}