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

来源:互联网 发布:用eclipse编写python 编辑:程序博客网 时间:2024/05/16 18:56

hdu2795  billbord

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


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

#include <iostream>#include <cstdio>using namespace std;#define lz 2*u,l,mid#define rz 2*u+1,mid+1,rconst 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]<w) return -1;  ///只需要判断此区间最大空余w是否大于w即可,节省好多时间    if(l==r)    {        return l;    }    int mid=(l+r)>>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);            }        }    }}


0 0
原创粉丝点击