九野的博客,转载请注明出处:http://blog.csdn.net/acmmmm/article/details/11949847
复制个题意:
题意,给你一个h*w的广告版,往上面贴1*wi的广告,求能够贴上且位置最上,最左的行hi;
解法:每次需找长度>=wi的最上最左位置,然后该位置长度-wi;
线段树data[]存放每个高度现有的宽度,区间找最大值,单点更新。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <math.h>
#include <queue>
#define N 201000
#define M 2000100
#define inf64 0x7ffffff
#define inf 0x7ffffff
#define ll int
#define L(x) x<<1
#define R(x) x<<1|1
#define Mid(x,y) (x+y)>>1
using namespace std;
inline ll Min(ll a,ll b){return a>b?b:a;}
inline ll Max(ll a,ll b){return a>b?a:b;}
ll len,maxdeep,Query;
struct node{
int l,r;
ll sum;
}tree[N*4];
void build(int l,int r,int id){
tree[id].l = l; tree[id].r = r;
tree[id].sum = maxdeep; //
if(l==r) return ;
int mid = Mid(l,r);
build(l,mid,L(id)); build(mid+1,r,R(id));
}
void updata_point(int pos,int id, ll data){//单点更新
if(tree[id].l == pos && pos == tree[id].r)
{ tree[id].sum += data; return ; }
int mid = Mid(tree[id].l, tree[id].r);
if(pos <= mid) updata_point(pos, L(id), data);
else updata_point(pos , R(id), data);
tree[id].sum = Max( tree[L(id)].sum , tree[R(id)].sum );
}
ll query_point(int pos, int id){ //单点询问
if(tree[id].l == pos && pos == tree[id].r)
return tree[id].sum ;
int mid = Mid(tree[id].l, tree[id].r);
if(pos <= mid) return query_point(pos, L(id));
else return query_point(pos, R(id));
}
ll query_inter(int l,int r,int id){
if( l <= tree[id].l && tree[id].r <= r)
return tree[id].sum;
int mid = Mid(tree[id].l , tree[id].r );
return Max( query_inter( l, r, L(id)) , query_inter( l, r, R(id)));
}
int find_rightmost(int data, int id){
if(tree[id].l == tree[id].r)return tree[id].l;
int mid = Mid( tree[id].l,tree[id].r);
if( query_inter( tree[id].l, mid, L(id)) >=data )return find_rightmost( data, L(id));
return find_rightmost( data, R(id));
}
int main(){
int n;
while(~scanf("%d %d %d",&len,&maxdeep,&Query)){
build(1,Min(len,Query),1);
while(Query--){
scanf("%d",&n);
if(tree[1].sum<n)
{printf("-1\n");continue;}
int pos = find_rightmost( n, 1);
updata_point( pos, 1, -n);
printf("%d\n",pos);
}
}
return 0;
}