HDU2795 Billboard 题解

HDU2795 Billboard

线段树例题解析合集

题意:有一个h行w列的矩形,在里面横放m条大小为1*l[i]的小长方形,不能重叠,如果能放得下,输出能放下的最小行数,放不下输出-1

由于只有m个长方形,最多只需要m行(h范围很大),把h对m取min

然后维护每行剩下的值的区间最大值,查询时若左子树代表区间内的最大值>需要的长度,向左子树递归,否则考虑右子树,若长度都不够,答案为-1

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
inline void read (int &x) {
    char ch = getchar(); x = 0;
    while (!isdigit(ch)) ch = getchar();
    while (isdigit(ch))  x = x * 10 + ch - 48, ch = getchar();
}
inline int print (int x) {
    if (x < 0) putchar ('-'), x = -x;
    if (x > 9) print (x / 10);
    putchar (x % 10 + 48);
}
int h, w, n, val, c[N << 2];
#define ls p << 1
#define rs p << 1 | 1
inline int Max (int a, int b) {return a > b ? a : b;}
int query (int p, int l, int r, int val) {
    if (l == r) {
        if (c[p] >= val) {c[p] -= val; return l;}
        else return -1;
    }
    int mid (l + r >> 1), ans (-1);
    if (c[ls] >= val) ans = query (ls, l, mid, val);
    else if (c[rs] >= val) ans = query (rs, mid + 1, r, val);
    c[p] = Max (c[ls], c[rs]);
    return ans;
}
int main() {
    while (~scanf ("%d %d %d", &h, &w, &n)) {
        if (n < h) h = n;
        for (int i = 1; i <= (h << 2); ++i) c[i] = w;
        for (int i = 1; i <= n; ++i) {
            read (val);
            if (val > w) puts ("-1");
            else print (query (1, 1, h, val)), puts ("");
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/whx666/p/12041534.html
今日推荐