hdu 2795 线段树入门题目

来源:互联网 发布:健步走计步器软件 编辑:程序博客网 时间:2024/06/04 19:13
题意:有一块h*w的墙,有N个宣传单 每个的大小为 1*wi 每次贴都从最左最上能贴的位置开始。求每一宣传单被贴在哪一行。

思路:线段树,以1~h划分区间,每一个区间中保存该区间能放下的最大长度,每次从最上面开始找,找到符合的位置 贴上,该位置减去len,更新区间的最大长度值。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2795

代码:

#include <iostream>#include <stdio.h>using namespace std;const int N=2000020;int h,w;struct Tree{    int l,r;    int res;}tree[N*4];int ans[N];void build(int root,int l,int r){    tree[root].l=l;    tree[root].r=r;    tree[root].res=w;    if(tree[root].l==tree[root].r)    {        return;    }    int mid=(r+l)/2;    build(root*2,l,mid);    build(root*2+1,mid+1,r);}int query(int root,int len){    if(tree[root].l==tree[root].r)    {        tree[root].res-=len;        return tree[root].l;    }    int ret;    if(tree[root*2].res>=len)    ret=query(root<<1,len);    else ret=query(root<<1|1,len);    tree[root].res=max(tree[root<<1].res,tree[root<<1|1].res);    return ret;}int main(){    int len,n;    while(scanf("%d%d%d",&h,&w,&n)!=EOF)    {        if(h>n) h=n;        build(1,1,h);        while(n--)        {            scanf("%d",&len);            if(len>tree[1].res)            printf("-1\n");            else            printf("%d\n",query(1,len));        }    }    return 0;}


0 0