题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=2795
树状数组做法:https://blog.csdn.net/moon_sky1999/article/details/81274345
线段树做法,复杂度O ( n log n ):
维护区间最大值,对于每次查询,如果左半段区间的最大值满足题意,就向左查询,否则向右。
代码:
#include <cstring>
#include <iostream>
#include <map>
#include <cmath>
#include <vector>
#include <string>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn=2e5+10;
struct tree {
int left, right;
int maxm;
}c[maxn<<2];
int a[maxn];
void build(int id,int l,int r) {
c[id].left = l;
c[id].right = r;
if (l == r) {
c[id].maxm = a[l];
return;
}
int mid = (l + r) >> 1;
build(id << 1, l, mid);
build(id << 1 | 1, mid + 1, r);
c[id].maxm = max(c[id << 1].maxm, c[id << 1 | 1].maxm);
}
int query_max(int id,int l,int r) {
if (c[id].left == l && c[id].right == r)return c[id].maxm;
int mid = (c[id].left + c[id].right) >> 1;
if (r <= mid)return query_max(id << 1, l, r);
else if (l > mid)return query_max(id << 1 | 1, mid + 1, r);
else return max(query_max(id << 1, l, mid), query_max(id << 1 | 1, mid + 1, r));
}
void update(int id,int pos,int v) {
if (c[id].left == c[id].right)c[id].maxm = v;
else {
int mid = (c[id].left + c[id].right) >> 1;
if (pos <= mid)update(id << 1, pos, v);
else update(id << 1 | 1, pos, v);
c[id].maxm = max(c[id << 1].maxm, c[id << 1 | 1].maxm);
}
}
int query(int id,int x) {
if (c[id].maxm < x)return -1;
if (c[id].left == c[id].right)return c[id].left;
else {
if (c[id << 1].maxm >= x)return query(id << 1, x);
else query(id << 1 | 1, x);
}
}
int main() {
/*ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);*/
int h, w, n;
while (~scanf("%d%d%d", &h, &w, &n)) {
for (int i = 1; i <= n; ++i)
a[i] = w;
build(1, 1, min(h, n));
int x;
for (int i = 1; i <= n; ++i) {
scanf("%d", &x);
int t = query(1, x);
if (t == -1) {
printf("%d\n", t);
} else {
a[t] -= x;
printf("%d\n", t);
update(1, t, a[t]);
}
}
}
return 0;
}