HDU 2795 Billboard 【线段树】

来源:互联网 发布:算法流程图用什么画 编辑:程序博客网 时间:2024/05/26 22:08

题目链接
Segment Tree, single-point update

题意

有一块h*w的告示板,要向上面贴一些广告,每张广告都想被贴得尽量靠顶端,然后再尽量靠左。现有n块尺寸分别是1*wi的广告(高度都为1)依次贴上去,问没张广告贴得位置。

分析

首先实际贴得行数肯定是min(h,n),开始没注意这个,被数据范围吓到了。然后这个问题只要记录每一行还剩下多少宽度,然后每贴一个广告就查找尽量靠左并且宽度大于等于它的。于是这就是一个单点更新的线段树,只不过查询的地方稍微改一下即可。

AC代码

//HDU 2795 Billboard//AC 2016-10-16 15:13:32//Segment tree#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cctype>#include <cstdlib>#include <cstring>#include <vector>#include <set>#include <string>#include <map>#include <queue>#include <deque>#include <list>#include <sstream>#include <stack>using namespace std;#define cls(x) memset(x,0,sizeof x)#define inf(x) memset(x,0x3f,sizeof x)#define neg(x) memset(x,-1,sizeof x)#define ninf(x) memset(x,0xc0,sizeof x)#define st0(x) memset(x,false,sizeof x)#define st1(x) memset(x,true,sizeof x)#define lowbit(x) x&(-x)#define input(x) scanf("%d",&(x))#define inputt(x,y) scanf("%d %d",&(x),&(y))#define bug cout<<"here"<<endl;//#pragma comment(linker, "/STACK:1024000000,1024000000")//stack expansion//#define debugconst double PI=acos(-1.0);const int INF=0x3f3f3f3f;//1061109567-2147483647const long long LINF=0x3f3f3f3f3f3f3f3f;//4557430888798830399-9223372036854775807const int maxn=200000+100;int h,w,n;/* 线段树 */struct segNode{    int left,right;//结点对应的区间端点    /*结点的性质*/    int remain;};struct segTree{    segNode tree[maxn*3+10];    /* 线段树构造函数 */    void build(int x,int left,int right)    {        tree[x].left=left;        tree[x].right=right;        if(left==right)//只有一个元素时        {            tree[x].remain=w;//储存单个元素的性质            return;        }        /*递归构造子树*/        int mid=(left+right)>>1;        build(x<<1,left,mid);        build(x<<1|1,mid+1,right);        /* 回溯更新当前结点依赖于子节点的性质 */        tree[x].remain=w;        return;    }    /* 线段树区间查询 */    int querry(int x,int v)    {        if(tree[x].remain<v)            return -1;        if(tree[x].left==tree[x].right)            return tree[x].left;        if(tree[x<<1].remain>=v)            return querry(x<<1,v);        else if(tree[x<<1|1].remain>=v)            return querry(x<<1|1,v);    }    /* 单点更新 */    void change(int x,int pos,int v)    {        if(tree[x].left==pos&&tree[x].right==pos)//找到这个点        {            /* 更新内容 */            tree[x].remain-=v;            return;        }        int mid=(tree[x].left+tree[x].right)>>1;        if(pos<=mid)            change(x<<1,pos,v);        else            change(x<<1|1,pos,v);        /* 回溯更新 */        tree[x].remain=max(tree[x<<1].remain,tree[x<<1|1].remain);        return;    }}billboard;int main(){    //ios::sync_with_stdio(false);    //cin.tie(0);    #ifdef debug        freopen("E:\\Documents\\code\\input.txt","r",stdin);        freopen("E:\\Documents\\code\\output.txt","w",stdout);    #endif    //IO    while(scanf("%d %d %d",&h,&w,&n)!=EOF)    {        int N=min(h,n);        billboard.build(1,1,N);        int ads=0,pos=0;        while(n--)        {            input(ads);            pos=billboard.querry(1,ads);            printf("%d\n",pos);            if(pos!=-1)                billboard.change(1,pos,ads);        }    }    return 0;}
0 0
原创粉丝点击