HDOJ 2795 Billboard(线段树基本操作)

题意:

有h * w的黑板,其中有n个人要把1 * wi的报贴上去,贴的时候要满足尽量靠上&&靠左。

输出每次张贴位置的行号。

思路:

线段树的区间为[1, h],树上节点代表所包含区间的最大宽度,初始化为w

#include <cstdio> #include <algorithm> using namespace std; #define lhs l, m, rt << 1 #define rhs m + 1, r, rt << 1 | 1  const int maxn = 200010; int seg[maxn << 2]; int h, w, n; void PushUp(int rt) {

    seg[rt] = max(seg[rt << 1], seg[rt << 1 | 1]); } void Build(int l, int r, int rt) { if (l == r)

        seg[rt] = w; else { int m = (l + r) >> 1;

        Build(lhs);

        Build(rhs);

        PushUp(rt); } } int Query(int wi, int l, int r, int rt) { int ret; if (l == r) {

        seg[rt] -= wi;

        ret = l; } else { int m = (l + r) >> 1; if (seg[rt << 1] >= wi)

            ret = Query(wi, lhs); else

            ret = Query(wi, rhs);

        PushUp(rt); } return ret; } int main() { while (scanf("%d %d %d", &h, &w, &n) != EOF) { if (h > n)

            h = n;



        Build(1, h, 1); for (int i = 0; i < n; ++i) { int wi;

            scanf("%d", &wi); if (seg[1] >= wi)

                printf("%d\n", Query(wi, 1, h, 1)); else

                printf("-1\n"); } } return 0; }

你可能感兴趣的:(基本操作)