http://acm.hdu.edu.cn/showproblem.php?pid=2795
在第一和第三多学校都出现线段树,我在比赛中并没有这样做。,热身下,然后31号之前把那两道多校的线段树都搞了,这是一道热身题
关键是建模:
首先一定看清楚题目构造的场景,看有什么特点--------会发现。假设尽量往左上放置的话。那么因为 the i-th announcement is a rectangle of size 1 * wi.,全然能够对h建立线段树。表示一行。结点里的l,r就表示从l行到r行,每次插入都更新结点里的可用宽度,同一时候插入的时候记录行数即可
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; #define lson(i) (i)*2,l,mid
#define rson(i) ((i)*2+1),mid+1,r
#define ll rt*2
#define rr (rt*2+1) const int MAXN = 200000 +10;
int n,w,h;
struct Node
{
int l,r;
int up;
}nodes[MAXN*4]; void build(int rt, int l, int r)
{
nodes[rt].l=l;
nodes[rt].r=r;
nodes[rt].up=w;
if(l == r)return;
int mid=(l+r)/2;
build(lson(rt));
build(rson(rt));
}
int cnt;
int ans[MAXN];
void update(int rt,int v)
{
if(nodes[rt].l == nodes[rt].r)
{
nodes[rt].up-=v;
ans[cnt]=nodes[rt].l ;
return;
}
if(v<=nodes[rt*2].up)update(rt*2,v);
else update(rt*2+1,v);
nodes[rt].up=max(nodes[rt*2].up, nodes[rt*2+1].up);
} int main()
{
int y;
while(~scanf("%d%d%d",&h, &w, &n))
{
cnt=0;
h=min(h,n);
build(1,1,h);
memset(ans,-1,sizeof(ans));
for(int i=0;i<n;i++)
{
scanf("%d",&y);
if(nodes[1].up>=y)update(1,y);
cnt++;
}
for(int i=0;i<n;i++)
printf("%d\n",ans[i]);
}
return 0;
}
版权声明:本文博客原创文章。博客,未经同意,不得转载。