九野的博客,转载请注明出处: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; }