单点更新区间求和贴海报问题 hdu2795 billbord

hdu2795  billbord

  题目大意:有一块板子,长宽分别为W,H,然后有n块1*w海报,让你把这n快海报贴在这块板子上,尽量板子的上方贴,同一行尽量往板子的左边贴。对于第i块海报如果能够贴下则输出能贴在第几行,否则输出-1。


    解题思路: 设线段树的操作长度为H,则对应的叶子节点的最大值为W。设每次找到符合要求的位置(板子最上最左,对应线段树中最下最左)减去相应的w值。   

#include 
#include 
using namespace std;

#define lz 2*u,l,mid
#define rz 2*u+1,mid+1,r
const int maxn=200005;
int tree[4*maxn];
int t_max[4*maxn];
int n, m, max_w, nn;

void build(int u, int l, int r)
{
    tree[u]=max_w;
    if(l==r)
    {
        return ;
    }
    int mid=(l+r)>>1;
    build(lz);
    build(rz);
}

void Update(int u, int l, int r, int id, int w)
{
    if(l==id&&id==r)
    {
        tree[u]-=w;
        return ;
    }
    int mid=(l+r)>>1;
    if(id<=mid)
        Update(lz,id,w);
    else Update(rz,id,w);
    tree[u]=max(tree[2*u],tree[2*u+1]);  ///向上更新最大子区间段

}

int Query(int u, int l, int r, int w)
{
    if(tree[u]>1;
    if(tree[2*u]>=w)
        return  Query(lz,w);
    else
        return  Query(rz,w);
}

int main()
{
    while(cin >> n >> max_w >> m)
    {
        nn=min(n,m);
        build(1,1,nn);
        while(m--)
        {
            int w;
            scanf("%d",&w);
            int id=Query(1,1,nn,w);
            if(id==-1) puts("-1");
            else
            {
                printf("%d\n",id);
                Update(1,1,nn,id,w);
            }
        }
    }
}


你可能感兴趣的:(线段树)