hdu-2795 Billboard(线段树)

题意:
有一块h*w的矩形广告板,要往上面贴广告;
然后给n个1*wi的广告,要求把广告贴上去;
而且要求广告要尽量往上贴并且尽量靠左;
求第n个广告的所在的位置,不能贴则为-1;
算法思想:
利用线段树可以求区间的最大值;
将位置即h用来建树(h<=n,大了没有意义);
树中存储的为该位置还拥有的空间;
若左子树的最大值大于他,就查询左子树,否则查询右子树;

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;

#define ll long long
const int maxn = 2e5 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int st[(maxn<<2) + 5];
int h, w, n;
void build(int o,int l,int r)
{
    st[o] = w;
    if(l == r)
        return;

    int m = l + ((r-l) >> 1);
    build(o << 1,l,m);
    build((o<<1)|1,m+1,r);
    //st[o] = max(st[o << 1],st[(o<<1)|1]);

}
void pushup(int o){
    st[o]=max(st[o<<1],st[o<<1|1]);
}

int query(int o,int l,int r,int ans)
{
    if(l == r)
    {
        st[o] -= ans;
        return l;
    }

    int m = l + ((r-l)>>1);
    int res;
    if(st[o<<1] >= ans)
        res = query(o<<1,l,m,ans);
    else
        res = query((o<<1)|1,m+1,r,ans);
    pushup(o);
    return res;
}
int main() {

    while(~scanf("%d%d%d", &h, &w, &n)) {
        if (h > n)
            h = n;
        build(1, 1, h);
        while (n--) {
            int x;
            scanf("%d", &x);
            if (st[1] < x)
                printf("-1\n");
            else {
                printf("%d\n", query(1, 1, h, x));
            }
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/smallhester/p/10498980.html
今日推荐