
这个本质是求线段树最长的全0区间
实际就是区间set
查询的时候二分查找
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
inline void read(int &x){
x=0;
int f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
x*=f;
}
const int N=2e5+10;
#define lc (p<<1)
#define rc (p<<1|1)
struct Segment_tree{
struct Node{
int len,lson,rson;
int lsum,rsum,sum;
int lazy;
}T[N<<2];
inline void PushUp(int p){
T[p].len=T[lc].len+T[rc].len;
T[p].sum=max(T[lc].sum,max(T[rc].sum,T[lc].rsum+T[rc].lsum));
if(T[lc].sum==T[lc].len)T[p].lsum=T[lc].len+T[rc].lsum;
else T[p].lsum=T[lc].lsum;
if(T[rc].sum==T[rc].len)T[p].rsum=T[rc].len+T[lc].rsum;
else T[p].rsum=T[rc].rsum;
}
inline void PushDown(int p){
if(T[p].lazy==1){//开房
T[lc].lazy=1;
T[rc].lazy=1;
T[lc].lsum=T[lc].rsum=T[lc].sum=0;
T[rc].lsum=T[rc].rsum=T[rc].sum=0;
}
if(T[p].lazy==2){//退房
T[lc].lazy=2;
T[rc].lazy=2;
T[lc].lsum=T[lc].rsum=T[lc].sum=T[lc].len;
T[rc].lsum=T[rc].rsum=T[rc].sum=T[rc].len;
}
T[p].lazy=0;
}
inline void build(int p,int l,int r){
T[p].lson=l;
T[p].rson=r;
if(l==r){
T[p].lazy=0;
T[p].sum=T[p].lsum=T[p].rsum=1;
T[p].len=1;
return;
}
int mid=(l+r)/2;
build(lc,l,mid);
build(rc,mid+1,r);
PushUp(p);
}
inline void Update(int p,int l,int r,int Flag){
if(l<=T[p].lson&&T[p].rson<=r){
// cout<<T[p].lson<<" "<<T[p].rson<<'\n';
if(Flag==1){
T[p].sum=T[p].rsum=T[p].lsum=0;
T[p].lazy=1;
return;
}
if(Flag==2){
T[p].sum=T[p].rsum=T[p].lsum=T[p].len;
T[p].lazy=2;
return;
}
}
PushDown(p);
int mid=(T[p].lson+T[p].rson)/2;
if(l<=mid)Update(lc,l,r,Flag);
if(mid< r)Update(rc,l,r,Flag);
PushUp(p);
}
inline int Query(int p,int l,int r,int x){
if(l==r)return l;
PushDown(p);
int mid=(l+r)/2;
if(T[lc].sum>=x)return Query(lc,l,mid,x);
else if(T[lc].rsum+T[rc].lsum>=x)return mid-T[lc].rsum+1;
else return Query(rc,mid+1,r,x);
}
}Tree;
int n,m;
int main(){
// freopen("2364.in","r",stdin);
read(n);
read(m);
Tree.build(1,1,n);
for(int i=1;i<=m;i++){
int opt;
int l,r,x;
read(opt);
if(opt==1){read(x);
// cout<<Tree.T[1].sum<<'\n';
if(Tree.T[1].sum>=x){
int left=Tree.Query(1,1,n,x);
cout<<left<<'\n';
Tree.Update(1,left,left+x-1,1);
}
else puts("0");
}
else{
read(l);
read(r);
r=l+r-1;
Tree.Update(1,l,r,2);
}
}
}

本文介绍了一种基于线段树的数据结构实现方法,用于处理区间内的元素更新及查询操作,特别适用于寻找最长连续全0区间的问题。文章通过具体代码示例详细解释了如何构建线段树、进行区间修改以及查询区间最大连续全0长度。

被折叠的 条评论
为什么被折叠?



