HDU 2795 Billboard [线段树-单点更新]

题意:

有一个广告牌,长是h宽为w。现在要在上面贴纸条做广告,每个纸条都是单位长度h=1,但是w宽不一致,要求尽可能的往顶头贴,再尽可能的往左边贴,求给出给定的纸条能贴在广告牌的第几行


分析:

每一行看作一个点,父节点记录最大还能插入的纸条


//AC CODE:

#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>

using namespace std;

#define Max(a,b) a>b?a:b
#define Min(a,b) a<b?a:b
#define _clr(str,val) memset(str,val,sizeof(str))

const int maxn = 222222;
int h , w , n;
int nowMax[maxn<<2];
void PushUP(int rt)
{
    nowMax[rt] = Max(nowMax[rt<<1] , nowMax[rt<<1|1]);
}
void build(int l,int r,int rt)
{
    nowMax[rt] = w;
    if (l == r) return ;
    int m = (l + r) >> 1;
    build(l , m , rt << 1);
    build(m + 1 , r , rt << 1 | 1);
}
int query(int x,int l,int r,int rt)
{
    if (l == r)
    {
        nowMax[rt] -= x;
        return l;
    }
    int m = (l + r) >> 1;
    int ret = (nowMax[rt<<1] >= x) ? query(x , l , m , rt << 1) : query(x , m + 1 , r , rt << 1 | 1);
    PushUP(rt);
    return ret;
}
int main()
{
    while (scanf("%d%d%d",&h,&w,&n)!=EOF)
    {
        if (h > n) h = n;
        build(1 , h , 1);
        while (n --)
        {
            int x;
            scanf("%d",&x);
            if (nowMax[1] < x)
                printf("-1\n");
            else
                printf("%d\n",query(x , 1 , h , 1));
        }
    }
    return 0;
}


你可能感兴趣的:(query,Build)