刚开始咋想也想不通10^9啊,肿么用线段树啊啊啊。
后来忍不住看人家的,才明白了。额。。。因为n最大为20W啊,只要开min(h,n)即可了。因为最多也就用n行。
这么一来就很好写了。线段树最后一层存的是每行的剩余量,然后父节点存当前子树中最大连续空余。然后类似二分查找即可。
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define BUG puts("here!!!")
using namespace std;
const int MAX = 200010;
struct Tnode{int l,r,val;};
Tnode node[MAX << 2];
int w;
void init()
{
memset(node,0,sizeof(node));
}
void Build(int t,int l,int r)
{
node[t].l = l; node[t].r = r;
if( node[t].l == node[t].r - 1 )
{
node[t].val = w;
return ;
}
int mid = MID(l,r);
Build(L(t),l,mid);
Build(R(t),mid,r);
node[t].val = max(node[L(t)].val,node[R(t)].val);
}
int Updata(int t,int l,int r,int val)
{
if( node[t].val < val ) return -1;
if( node[t].l == node[t].r - 1 && node[t].val >= val )
{
node[t].val -= val;
return node[t].r;
}
int mid = MID(node[t].l,node[t].r);
int ans = -1;
if( val <= node[L(t)].val )
ans = Updata(L(t),l,r,val);
else
if( val <= node[R(t)].val )
ans = Updata(R(t),l,r,val);
node[t].val = max(node[L(t)].val,node[R(t)].val);
return ans;
}
int main()
{
int h,n,d;
while( ~scanf("%d%d%d",&h,&w,&n) )
{
Build(1,0,min(h,n));
for(int i=0; i<n; i++)
{
scanf("%d",&d);
int ans = Updata(1,0,n,d);
printf("%d\n",ans);
}
}
return 0;
}