传送门----点击打开链接
题意:
给定一个值k,求第一个使得[L,L+k]均为0。
思路:线段树区间合并
Left:左端点开始连续的最大值
Right:右端点开始连续得最大值
Sum:区间内符合条件得最大值
CODE:
#include<cstdio>
#include<iostream>
#include<algorithm>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define N 50005<<2
int sum[N],st[N],Left[N],Right[N];
using namespace std;
void Push_up(int rt,int m)
{
Left[rt]=Left[rt<<1];
Right[rt]=Right[rt<<1|1];
if(Left[rt]==(m-(m>>1)))
Left[rt]+=Left[rt<<1|1];
if(Right[rt]==(m>>1))
Right[rt]+=Right[rt<<1];
sum[rt]=max(Left[rt<<1|1]+Right[rt<<1],max(sum[rt<<1],sum[rt<<1|1]));
}
void Push_down(int rt,int m)
{
if(st[rt]!=-1)
{
st[rt<<1]=st[rt<<1|1]=st[rt];
sum[rt<<1]=Left[rt<<1]=Right[rt<<1]= st[rt]==0?(m-(m>>1)):0;
sum[rt<<1|1]=Left[rt<<1|1]=Right[rt<<1|1]= st[rt]==0?(m>>1):0;
st[rt]=-1;
}
}
void Build(int l,int r,int rt)
{
int m=(l+r)>>1;
st[rt]=-1;
sum[rt]=Right[rt]=Left[rt]=r-l+1;
if(l==r)
return;
Build(lson);
Build(rson);
}
void Update(int L,int R,int val,int l,int r,int rt)
{
int m=(l+r)>>1;
if(L<=l&&R>=r)
{
Left[rt]=Right[rt]=sum[rt]=(val==0?(r-l+1):0);
st[rt]=val;
return;
}
Push_down(rt,r-l+1);
if(L<=m)
Update(L,R,val,lson);
if(R>m)
Update(L,R,val,rson);
Push_up(rt,r-l+1);
}
int Query(int val,int l,int r,int rt)
{
int m=(l+r)>>1;
if(l==r)
return 1;
Push_down(rt,r-l+1);
if(sum[rt<<1]>=val)
return Query(val,lson);
else if(Right[rt<<1]+Left[rt<<1|1]>=val)
return m-Right[rt<<1]+1; //First Satisfy
else
return Query(val,rson);
}
int main()
{
int n,q,a,b,res,op;
while(scanf("%d%d",&n,&q)==2)
{
Build(1,n,1);
while(q--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d",&a);
if(sum[1]<a)
printf("0\n");
else
{
res=Query(a,1,n,1);
printf("%d\n",res);
Update(res,res+a-1,1,1,n,1);
}
}
else
{
scanf("%d%d",&a,&b);
Update(a,a+b-1,0,1,n,1);
}
}
}
return 0;
}