一眼就知道是线段树区间合并,模板在,我就不解释了。
在这道题中,
query()
q
u
e
r
y
(
)
被改成了
insert()
i
n
s
e
r
t
(
)
,现在来讲讲如何实现
insert()
i
n
s
e
r
t
(
)
。
因为2操作就是
set()
s
e
t
(
)
,所以自动略过。
考虑1操作:
首先在读入X后,用区间最大连续区间(即sum[1])与x进行比较,如果
sum[1]<x
s
u
m
[
1
]
<
x
,那直接输出0就可以了,否则执行
insert()
i
n
s
e
r
t
(
)
,
由于题目要求的是空区间要尽量靠左,所以查找的时候优先考虑左边,因此分三种情况:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define max(x, y) ((x) > (y) ? (x) : (y))
struct SegTree { //和模板中0和1掉了个头
#define lc(o) o << 1
#define rc(o) o << 1 | 1
#define mid ((l + r) >> 1)
static const int MAXSIZE = 100000 + 5;
int lsum[MAXSIZE << 2], rsum[MAXSIZE << 2], sum[MAXSIZE << 2], color[MAXSIZE << 2];
void creat(int o, int l, int r, int value) {
color[o] = value;
lsum[o] = rsum[o] = sum[o] = value == 0 ? r - l + 1 : 0;
}
void pushdown(int o, int l, int r) {
if (color[o] != -1) {
creat(lc(o), l, mid, color[o]);
creat(rc(o), mid + 1, r, color[o]);
}
}
void pushup(int o, int l, int r) {
lsum[o] = color[lc(o)] == 0 ? lsum[lc(o)] + lsum[rc(o)] : lsum[lc(o)];
rsum[o] = color[rc(o)] == 0 ? rsum[lc(o)] + rsum[rc(o)] : rsum[rc(o)];
sum[o] = max(rsum[lc(o)] + lsum[rc(o)], max(sum[lc(o)], sum[rc(o)]));
if (sum[o] == 0) color[o] = 1;
else if (sum[o] == r - l + 1) color[o] = 0;
else color[o] = -1;
}
void set(int o, int l, int r, int L, int R, int value) {
if (l > R || r < L) return;
else if (L <= l && r <= R) creat(o, l, r, value);
else {
pushdown(o, l, r);
set(lc(o), l, mid, L, R, value);
set(rc(o), mid + 1, r, L, R, value);
pushup(o, l, r);
}
}
int insert(int o, int l, int r, int x) {
if (l > r) return 0;
if (l == r) return l; //情况1
pushdown(o, l, r);
if (sum[lc(o)] >= x) return insert(lc(o), l, mid, x); //情况2
else if (rsum[lc(o)] + lsum[rc(o)] >= x) return mid - rsum[lc(o)] + 1; //情况3
else return insert(rc(o), mid + 1, r, x); //情况4
}
void build(int o, int l, int r) {
if (l > r) return;
else if (l == r) creat(o, l, r, 0);
else {
build(lc(o), l, mid);
build(rc(o), mid + 1, r);
pushup(o, l, r);
}
}
}root;
int main() {
int n, m;
scanf("%d%d", &n, &m);
root.build(1, 1, n);
for (int i = 1; i <= m; i++) {
int opt, x, y;
scanf("%d", &opt);
if (opt == 1) {
scanf("%d", &x);
if (root.sum[1] < x) { //确认存在满足的解
puts("0");
continue;
}
int ret = root.insert(1, 1, n, x); //找到解
root.set(1, 1, n, ret, ret + x - 1, 1); //将找到的解得区间直接覆盖成1
printf("%d\n", ret);
}
else {
scanf("%d%d", &x, &y);
root.set(1, 1, n, x, x + y - 1, 0); //覆盖为0
}
}
return 0;
}
因篇幅问题不能全部显示,请点此查看更多更全内容