题目大意
我用自己的话概括一下,给一段长为n的空区间,有2种操作,一种就是找到最左边长为w的连续的空区间并返回这段空区间最左边的区间号。另一种就是将从区间号a开头长度为b的这一段区间清空。
题目分析
这道题是关于线段树区间合并的基础题,不过自己想了很久,自己也写了十几篇的线段树的博客有了自己线段树的风格,其实个人感觉挺简约的,看着也挺舒服,感觉封装在结构体中挺丑的,什么都要加个前缀。
合并的时候需要处理的点挺多的,这里我就不一一列举了,详细的看我的代码。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define mid (L+R)/2
#define lson o<<1, L, mid
#define rson o<<1|1, mid+1, R
const int maxn = 50005;
int lsum[maxn<<2],rsum[maxn<<2],msum[maxn<<2];
int cover[maxn<<2]; // 延迟标记
void pushdown(int o,int m) //标记往下
{
if(cover[o] != -1) //等于1表示这些房子住了,等于0表示住的人走了
{
cover[o<<1] = cover[o<<1|1] = cover[o];
msum[o<<1] = lsum[o<<1] = rsum[o<<1] = cover[o]? 0 : m - (m >> 1);
msum[o<<1|1] = lsum[o<<1|1] = rsum[o<<1|1] = cover[o] ? 0 : (m >> 1);
cover[o] = -1;
}
}
void pushup(int o,int m) //这里大家可以仔细想一下,很容易理解
{
lsum[o] = lsum[o<<1];
rsum[o] = rsum[o<<1|1];
if(lsum[o] == m-(m>>1)) lsum[o] += lsum[o<<1|1];
if(rsum[o] == (m>>1)) rsum[o] += rsum[o<<1];
msum[o] = max(rsum[o<<1]+lsum[o<<1|1], max(msum[o<<1], msum[o<<1|1]));
}
void build(int o,int L,int R)
{
msum[o] = rsum[o] = lsum[o] = (R-L+1);
cover[o] = -1;
if(L == R) return ;
build(lson);
build(rson);
}
void update(int o,int L,int R,int l,int r,int c)
{
if(l <= L && R <= r){
msum[o] = lsum[o] = rsum[o] = c?0:R-L+1;
cover[o] = c;
return ;
}
pushdown(o, R-L+1); //标记向下推移
if(l <= mid) update(lson, l, r, c);
if(mid < r) update(rson, l, r, c);
pushup(o, R-L+1); //同时更新父亲结点的信息
}
int query(int o,int L,int R,int w) //返回最左边的能容纳长为w的区间的左端点,注意是找最左边
{
if(L == R) return L; //这一点不能掉了
pushdown(o, R-L+1);
if(msum[o<<1] >= w) return query(lson,w); //左区间有就到左孩子区间
else if(rsum[o<<1] + lsum[o<<1|1] >= w) //处于左区间与右区间的中间
return mid - rsum[o<<1] + 1;
else
return query(rson,w); //只能找右区间了
}
int main()
{
int n,m;
scanf("%d%d", &n, &m);
build(1, 1, n);
while(m--){
int op,a,b;
scanf("%d", &op);
if(op == 1)
{
scanf("%d", &a);
if(msum[1] < a) //如果根没有,那么一定没有
printf("0\n");
else{
int p = query(1, 1, n, a);
printf("%d\n", p);
update(1, 1, n, p, p+a-1, 1);
}
}
else
{
scanf("%d%d", &a, &b);
update(1, 1, n, a, a+b-1, 0);
}
}
return 0;
}