看到数据吓尿了...h,w都是10^9...感觉线段树无从下手!..看了大牛的分析..大彻大悟..因为一个announcement最多占一行...而announcement的总数n<=200000...所以纵使高度h能达到10^9..能用上的最多也就前200000个..
构图..每个叶子节点代表每个行所剩下能用的格子数...非叶子节点表示其孩子中格子数最多为多少...
当要插入一个announcement时..从整个线段树的根节点开始..尽量往左边走(其子树的最大格子数要大于当前的wi)....走到叶子节点..输出这个叶子节点的代表的行号..结束记得调整线段树...在这个位置减去wi并且更新上去...
Program:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<set>
#include<ctime>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
#define oo 100000007
#define ll long long
#define pi acos(-1.0)
#define MAXN 200005
using namespace std;
int MAX[MAXN<<2],h,w,n;
void updata(int x,int w,int l,int r,int now)
{
if (l==r)
{
MAX[now]+=w;
return;
}
int mid=(l+r)>>1;
if (x<=mid) updata(x,w,l,mid,now<<1);
else updata(x,w,mid+1,r,(now<<1)|1);
MAX[now]=max(MAX[now<<1],MAX[(now<<1)|1]);
return;
}
int query(int x,int l,int r,int now)
{
if (MAX[now]<x) return -1;
if (l==r) return l;
int mid=(l+r)/2;
if (MAX[now<<1]>=x) return query(x,l,mid,now<<1);
if (MAX[(now<<1)|1]>=x) return query(x,mid+1,r,(now<<1)|1);
}
int main()
{
int i,m;
while (~scanf("%d%d%d",&h,&w,&n))
{
memset(MAX,0,sizeof(MAX));
h=min(h,n);
for (i=1;i<=h;i++) updata(i,w,1,h,1);
while (n--)
{
int x,t;
scanf("%d",&x);
t=query(x,1,h,1);
printf("%d\n",t);
if (t>0) updata(t,-x,1,h,1);
}
}
return 0;
}