题目链接: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;
}