题意:
有一个H*W的广告牌,当插入一个广告时(1*Wi),问最靠前的插入方式是什么
新生赛有个类似的题目,可惜当时居然没水过去。
果断用线段树做 以H为线段 建树,存[l,r]中最大的宽度,因为区间最大值满足区间和性质。
所以线段树几个要素如下:
线段:H
区间和性质:最大值
代码:
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#define oo 0x13131313
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 222222
using namespace std;
int h,w,n;
int tree[maxn*4];
int A[maxn];
void PushUp(int rt)
{
tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);
}
int build(int l,int r,int rt)
{
if(l==r) {tree[rt]=w;return 0;}
int m=(l+r)>>1;
build(lson);
build(rson);
PushUp(rt);
} void input()
{
for(int i=1;i<=n;i++)
scanf("%d",&A[i]);
}
int updata(int p,int k,int l,int r,int rt)
{
int m;
if(l==r) {tree[rt]+=k;return 0;}
m=(l+r)>>1;
if(p<=m) updata(p,k,lson);
else updata(p,k,rson);
PushUp(rt);
}
int query(int p,int l,int r,int rt)
{
if(p>tree[rt]) return -1;
if(l==r) return l;
int m=(l+r)>>1;
if(p<=tree[rt<<1]) return query(p,lson);
else return query(p,rson);
}
void solve()
{
for(int i=1;i<=n;i++)
{
int t=query(A[i],1,h,1);
printf("%d\n",t);
if(t!=-1)
{
updata(t,-A[i],1,h,1);
}
}
}
void init()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
}
int main()
{
// init();
while(scanf("%d%d%d",&h,&w,&n)!=EOF)
{
memset(tree,0,sizeof(tree));
h=min(h,200000);
build(1,h,1);
input();
solve();
}
return 0;
}