这个题一开始有点傻,用的求和的线段树,多了很多无用的查找步骤,然后超时,然后优化了好久才想起来用区间最大值可以避免很多无用查找层次,然后重写。
经过不断的改写,重写,初步掌握线段树的灵活飘逸的代码风格。
code:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn=200100;
int sumtree[maxn<<2];
void pushUp(int rt)
{
sumtree[rt]=max(sumtree[rt<<1],sumtree[rt<<1|1]);
}
void build(int w,int l,int r,int rt)
{
if(l==r)
{
sumtree[rt]=w;
return ;
}
int m=(l+r)/2;
build(w,lson);
build(w,rson);
pushUp(rt);
}
void updateandQuery(int w,int l,int r,int rt)
{
//printf("l=%d-------r=%d\n",l,r);
if(l==r&&sumtree[rt]>=w)
{
sumtree[rt]-=w;
printf("%d\n",l);
return;
}
int m=(l+r)/2;
if(w<=sumtree[rt<<1])
{
updateandQuery(w,lson);
}
else if(w<=sumtree[rt<<1|1])
{
updateandQuery(w,rson);
}
pushUp(rt);
//printf("sum[%d]=%d",rt,sumtree[rt]);
}
int main()
{
int h,w,n,x;
while(scanf("%d%d%d",&h,&w,&n)!=EOF)
{
int na=min(n,h);
memset(sumtree,0,sizeof(sumtree));
build(w,1,na,1);
for(int i=0;i<n;i++)
{
scanf("%d",&x);
if(x>sumtree[1])
printf("-1\n");
else
updateandQuery(x,1,na,1);
}
}
return 0;
}