【ICPC-427】hdu 2795 Billboard

点击打开hdu 2795

思路: 线段树+单点更新

分析:

1 题目的意思是给定一个h*w的广告牌h为高,w为宽,现在有n个高为1宽为wi的小广告要放上去,原则是最先放最上面和最左边的位置

2 题目的h和w的最大值为10^9,但是n最大为200000。所以我们可以知道最多用掉的广告牌就是x = min(n , h),而这个值就是200000,所以我们可以把每一行作为一个点来利用线段树,线段树的区间[i , j]存储的是第i行到第j行的最大的剩余空间,那么我们只要每一次去查找整个区间[1 , x] ,然后我们要优先的考虑左子树,这样就能够满足要求的条件了

 

代码;

 


/************************************************
 * By: chenguolin                               * 
 * Date: 2013-09-02                             *
 * Address: http://blog.csdn.net/chenguolinblog *
 ************************************************/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

#define Lson(x) (x<<1)
#define Rson(x) (Lson(x)|1)
#define Mid(x,y) ((x+y)>>1)
#define Sum(x,y) (x+y)

typedef long long int64;
const int MAXN = 200010;

int h , w , n;
struct Node{
    int left;
    int right;
    int64 maxVal;
};
Node node[4*MAXN];

void push_up(int pos){
    node[pos].maxVal = max(node[Lson(pos)].maxVal , node[Rson(pos)].maxVal);
}

void init(int left , int right , int pos){
    node[pos].left = left;
    node[pos].right = right;
    if(node[pos].left == node[pos].right){
        node[pos].maxVal = w;
        return;
    }
    int mid = Mid(left , right);
    init(left , mid , Lson(pos));
    init(mid+1 , right , Rson(pos));
    push_up(pos);
}

void update(int index , int val , int pos){
    if(node[pos].left == node[pos].right){
        node[pos].maxVal -= val;
        return;
    }
    int mid = Mid(node[pos].left , node[pos].right);
    if(index <= mid) 
        update(index , val , Lson(pos));
    else
        update(index , val , Rson(pos));
    push_up(pos);
}

int query(int left , int right , int val , int pos){
    if(node[pos].maxVal < val)
        return -1;
    if(left == right)
        return node[pos].maxVal >= val ? left : -1;
    int mid = Mid(left , right);
    int ans = query(left , mid , val , Lson(pos));
    if(ans == -1)
        return query(mid+1 , right , val , Rson(pos));
    else
        return ans;
}

void input(){
    int m = n;
    int i , x;
    n = min(n , h);
    init(1 , n , 1);
    while(m--){
        scanf("%d" , &x);
        int ans = query(1 , n , x , 1);
        printf("%d\n" , ans);
        if(ans != -1)
           update(ans , x , 1);
    }
}

int main(){
    while(scanf("%d%d%d" , &h , &w , &n) != EOF)
        input();
    return 0;
}

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值