HDU2795 Billboard 线段树

题目链接:hdu2795

题意:有一个广告牌大小为h*w。有n个广告,每个广告高度为1,宽度为wi,要把广告贴到广告牌上。要求尽可能往上贴。并输出每个广告贴在第几行,如果不能贴上去则输出-1。

思路:可以用线段树来维护每个区间剩余打最大宽度。初始状态每个点值为w。每次查询的时候,如果左子树最大值大于wi,则往左子树查询,反之往右子树查询。

code:

#include <bits/stdc++.h>

using namespace std;
#define mid ((r+l)>>1)
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r

const int maxn = 2e5 + 10;
int tree[maxn << 2];
int h, w, n;

void build(int rt, int l, int r) {
    if (l == r) {
        tree[rt] = w;
        return;
    }
    build(lson);
    build(rson);
    tree[rt] = max(tree[rt << 1], tree[rt << 1 | 1]);
}

int query(int rt, int l, int r, int wi) {
    if (l == r) {
        tree[rt] -= wi;
        return l;
    }
    int ans = 0;
    if (tree[rt << 1] >= wi)
        ans = query(lson, wi);
    else
        ans = query(rson, wi);
    tree[rt] = max(tree[rt << 1], tree[rt << 1 | 1]);
    return ans;
}

int main() {
    ios::sync_with_stdio(false);
    while (cin >> h >> w >> n) {
        int size = n;
        size = min(h, n); //区间大小选择h或者n中比较小的那个即可。假设每行只能贴一个广告,如果n>h,那么最多也只能贴h行。如果h>n,那么最多也只能贴n行。
        build(1, 1, n);
        int i, wi;
        for (i = 0; i < n; i++) {
            cin>>wi;
            if(tree[1]<wi)
                cout<<-1<<endl;
            else
                cout<<query(1,1,size,wi)<<endl;
        }
    }
    return 0;
}
发布了50 篇原创文章 · 获赞 52 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_43058685/article/details/104071064
今日推荐