Description
有一间旅馆,旅馆内有n间排成一排的房间,一开始全为空。现在有m个要求:
1 d表示询问旅馆内是否有连续d间空房间,有的话则输出最小的一个r,满足从r开始连续d间房间均为空,同时会有人入住这d间房。若无法被满足,则输出0.
2 l r表示把[l,r]内的房间全部设为空。
Input
第一行两个整数n,m.
接下来m行,每行描述一个操作。
Output
对于每一个1操作,输出一行表示答案。
Hint
【数据规模与约定】
对于30%的数据,n,m<=1000
对于100%的数据,n,m<=50000,d,l,r<=n
Source
BY BPM
Solution
线段树区间合并
考虑用llen、rlen、len分别记录区间左起最长连续0、右起最长连续0、最长连续0,查询的时候优先查询左子树即可。合并的时候分情况讨论一下就行了。
心疼基哥500行+程序wa了
Code
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <queue>
#include <vector>
#include <algorithm>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define drp(i, st, ed) for (int i = st; i >= ed; i -= 1)
#define erg(i, st) for (int i = ls[st]; i; i = e[i].next)
#define fill(x, t) memset(x, t, sizeof(x))
#define max(x, y) (x)>(y)?(x):(y)
#define min(x, y) (x)<(y)?(x):(y)
#define ll long long
#define db double
#define INF 0x3f3f3f3f
#define N 100001
struct treeNode{int l, r, llen, rlen, len, lazy;}t[N << 2 | 1];
inline int read() {
int x=0,v=1; char ch=getchar();
while (ch<'0'||ch>'9'){if(ch=='-')v=-1; ch=getchar();}
while (ch<='9'&&ch>='0'){x=x*10+ch-'0'; ch=getchar();}
return x*v;
}
inline void pushDown(int now) {
if (t[now].lazy == 1) {
t[now << 1].lazy = t[now << 1 | 1].lazy = 1;
t[now << 1].llen = t[now << 1].rlen = t[now << 1].len = 0;
t[now << 1 | 1].llen = t[now << 1 | 1].rlen = t[now << 1 | 1].len = 0;
t[now].lazy = 0;
}else if (t[now].lazy == 2) {
t[now << 1].lazy = t[now << 1 | 1].lazy = 2;
t[now << 1].llen = t[now << 1].rlen = t[now << 1].len = t[now << 1].r - t[now << 1].l + 1;
t[now << 1 | 1].llen = t[now << 1 | 1].rlen = t[now << 1 | 1].len = t[now << 1 | 1].r - t[now << 1 | 1].l + 1;
t[now].lazy = 0;
}
}
inline void pushUp(int now) {
if (t[now << 1].r - t[now << 1].l + 1 == t[now << 1].llen){
t[now].llen = t[now << 1].llen + t[now << 1 | 1].llen;
}else {
t[now].llen = t[now << 1].llen;
}
if (t[now << 1 | 1].r - t[now << 1 | 1].l + 1 == t[now << 1 | 1].rlen){
t[now].rlen = t[now << 1].rlen + t[now << 1 | 1].rlen;
}else {
t[now].rlen = t[now << 1 | 1].rlen;
}
t[now].len = max(t[now << 1].rlen + t[now << 1 | 1].llen, max(t[now << 1].len, t[now << 1 | 1].len));
}
inline int query(int now, int d) {
pushDown(now);
if (t[now].l == t[now].r) {
return 1;
}else if (t[now << 1].len >= d) {
return query(now << 1, d);
}else if (t[now << 1].rlen + t[now << 1 | 1].llen >= d) {
return t[now << 1].r - t[now << 1].rlen + 1;
}else {
return query(now << 1 | 1, d);
}
}
inline void modify(int now, int l, int r) {
pushDown(now);
if (t[now].l == l && t[now].r == r) {
t[now].lazy = 1;
t[now].llen = t[now].rlen = t[now].len = 0;
return ;
}
int mid = (t[now].l + t[now].r) >> 1;
if (r <= mid) {
modify(now << 1, l, r);
}else if (l > mid) {
modify(now << 1 | 1, l, r);
}else {
modify(now << 1, l, mid);
modify(now << 1 | 1, mid + 1, r);
}
pushUp(now);
}
inline void clear(int now, int l, int r) {
pushDown(now);
if (t[now].l == l && t[now].r == r) {
t[now].lazy = 2;
t[now].llen = t[now].rlen = t[now].len = t[now]. r - t[now].l + 1;
return ;
}
int mid = (t[now].l + t[now].r) >> 1;
if (r <= mid) {
clear(now << 1, l, r);
}else if (l > mid) {
clear(now << 1 | 1, l, r);
}else {
clear(now << 1, l, mid);
clear(now << 1 | 1, mid + 1, r);
}
pushUp(now);
}
inline void build(int now, int l, int r) {
t[now] = (treeNode){l, r, r - l + 1, r - l + 1, r - l + 1};
if (l == r){return ;}
int mid = (t[now].l + t[now].r) >> 1;
build(now << 1, l, mid);
build(now << 1 | 1, mid + 1, r);
}
int main(void) {
int n = read();
int m = read();
build(1, 1, n);
while (m --) {
int opt = read();
if (opt == 1) {
int d = read();
if (d > t[1].len) {puts("0"); continue;}
int pos = query(1, d); modify(1, pos, pos + d - 1);
printf("%d\n", pos);
} else if (opt == 2) {
int l = read();
int r = read();
clear(1, l, r);
}
}
return 0;
}