题意:
一家旅馆有N(1 ≤ N ≤ 50000)间房间,并且所有的房间都是连续排列在同一边,现在每个观光团需要入住房间,要求房间的编号为连续的r...r+Di−1,并且r是最小的;
参观者同样可能退房,并且他们每次退房都是编号为Xi...Xi+Di−1 (1≤Xi≤N−Di+1)的房间。
现在有两种操作:
1. 1 a 每个观光团需要入住a间编号连续的房间
2. 2 a b 观光者需要退房间,其中房间编号是 a...a+b−1
要求对于每次询问,输出为观光团分配数目为a的房间中编号最小的房间编号
解析:
利用线段树建立模型,维护最大连续区间长度,其中区间长度就是对应的房间数目,并且对应区间中最左边的断点就是答案,同时因为需要求出连续区间的最大长度,因此每次pushUp时都将左右区间合并,
lsum维护左区间的最大长度,
rsum维护右区间的最大长度,
msum维护区间1...N中的最大连续区间长度,
cover标志对应区间是否为空。
my code
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ls o<<1
#define rs o<<1|1
#define lson ls, L, M
#define rson rs, M+1, R
using namespace std;
const int N = 50005;
int cover[N<<2]; //懒惰标记 -1无操作,0区间为空,1区间为满
int lsum[N<<2], rsum[N<<2], msum[N<<2];
int n, m;
void pushDown(int o, int L, int R) {
if(cover[o] != -1) {
int M = (L + R)/2;
cover[ls] = cover[rs] = cover[o];
lsum[ls] = rsum[ls] = msum[ls] = cover[o] ? 0 : (M - L + 1);
lsum[rs] = rsum[rs] = msum[rs] = cover[o] ? 0 : (R - M);
cover[o] = -1;
}
}
void pushUp(int o, int L, int R) {
int M = (L + R)/2;
int len1 = M - L + 1, len2 = R - M;
lsum[o] = lsum[ls]; rsum[o] = rsum[rs];
if(lsum[o] == len1) lsum[o] += lsum[rs];
if(rsum[o] == len2) rsum[o] += rsum[ls];
msum[o] = max(msum[ls], max(msum[rs], rsum[ls] + lsum[rs]));
if(cover[ls] == cover[rs]) cover[o] = cover[ls];
else cover[o] = -1;
}
void modify(int o, int L, int R, int ql, int qr, int val) {
if(ql <= L && R <= qr) {
cover[o] = val;
lsum[o] = rsum[o] = msum[o] = (val) ? 0 : (R-L+1);
return ;
}
pushDown(o, L, R);
int M = (L + R)/2;
if(ql <= M) modify(lson, ql, qr, val);
if(qr > M) modify(rson, ql, qr, val);
pushUp(o, L, R);
}
int query(int o, int L, int R, int need) {
if(L == R) return L;
pushDown(o, L, R);
int M = (L + R)/2;
if(msum[ls] >= need)
return query(lson, need);
else if(lsum[rs] + rsum[ls] >= need)
return M - rsum[ls] + 1;
else return query(rson, need);
}
void build(int o, int L, int R) {
cover[o] = -1;
lsum[o] = rsum[o] = msum[o] = R - L + 1;
if(L == R) return ;
int M = (L + R)/2;
build(lson);
build(rson);
}
int main() {
while(scanf("%d%d", &n, &m) != EOF) {
build(1, 1, n);
int oper, ql, qr, need;
while(m--) {
scanf("%d", &oper);
if(oper == 1) {
scanf("%d", &need);
if(msum[1] < need) {
puts("0");
continue;
}
ql = query(1, 1, n, need);
printf("%d\n", ql);
qr = ql + need - 1;
modify(1, 1, n, ql, qr, 1);
}else {
scanf("%d%d", &ql, &need);
qr = ql + need - 1;
modify(1, 1, n, ql, qr, 0);
}
}
}
return 0;
}