1
4
7
0
5
线段树区间合并裸题 我们设这样几个数组 : max_near、max_l、max_r、lazy来分别表示区间最大连续长度,从左开始的最大连续长度,从右开始的区间最大连续长度、懒度标记
这样 我们的max_near就是max(max(max_near[lc],max_near[rc]),max_r[lc]+max_r[lc]) 对于max_l的维护,若左儿子的max_next等于len,那么就是左儿子的len加右儿子max_l,否则是左儿子的max_l,max_r类似。
对于每次查询,如果max_near[root] < query ,那么直接输出0即可,否则的话以 左子树? 左子树右加右子树左 ? 右子树的顺序选择递归,返回ans并从ans+query的区间范围对树进行修改。
代码:
#include<bits/stdc++.h>
#define re register int
using namespace std;
int n,m,o;
int a,d,x,maxx;
int max_near[500100],max_l[500100],max_r[500100],len[500100],lazy[500100],cl[500100],cr[500100];
void pp(int k)
{
max_l[k]=max_l[k<<1];
max_r[k]=max_r[k<<1|1];
if(max_l[k]==(cr[k<<1]-cl[k<<1]+1))
max_l[k]+=max_l[k<<1|1];
if(max_r[k]==(cr[k<<1|1]-cl[k<<1|1]+1))
max_r[k]+=max_r[k<<1];
max_near[k]=max(max_r[k<<1]+max_l[k<<1|1],max(max_near[k<<1],max_near[k<<1|1]));
/*
错误搞法
len[k]=len[k<<1]+len[k<<1|1];
max_l[k]=(max_near[k<<1]==len[k<<1])?(len[k<<1]+max_l[k<<1|1]):max_l[k<<1];
max_r[k]=(max_near[k<<1|1]==len[k<<1|1])?(len[k<<1|1]+max_r[k<<1]):max_r[k<<1|1];
max_near[k]=max_r[k<<1]+max_l[k<<1|1];
*/
return;
}
void build(int k,int l,int r)
{
cl[k]=l;
cr[k]=r;
lazy[k]=-1;
if(l==r)
{
max_l[k]=max_r[k]=max_near[k]=len[k]=1;
return;
}
int m=(l+r)>>1;
build(k<<1,l,m);
build(k<<1|1,m+1,r);
pp(k);
}
void pushdown(int r,int lc,int rc)
{
if(lazy[r]!=-1)
{
lazy[lc]=lazy[rc]=lazy[r];
if(lazy[r])
{
max_near[lc]=max_l[lc]=max_r[lc]=len[lc]=0;
max_near[rc]=max_l[rc]=max_r[rc]=len[rc]=0;
}
else
{
max_near[lc]=max_l[lc]=max_r[lc]=len[lc]=cr[lc]-cl[lc]+1;
max_near[rc]=max_l[rc]=max_r[rc]=len[rc]=cr[rc]-cl[rc]+1;
}
lazy[r]=-1;
}
}
int que(int k,int d)
{
int m=(cl[k]+cr[k])>>1;
if(cl[k]==cr[k])
return cl[k];
/*
错误,因为开端不一定在最左边!
if(max_near[k]==d)
return cl[k];
*/
pushdown(k,k<<1,k<<1|1);
if(max_near[k<<1]>=d)
return que(k<<1,d);
if(max_r[k<<1]+max_l[k<<1|1]>=d)
return m-max_r[k<<1]+1;
else
return que(k<<1|1,d);
}
void updata(int l,int r,int root,int z)
{
if(l<=cl[root]&&cr[root]<=r)
{
lazy[root]=z;
if(z)
max_near[root]=max_l[root]=max_r[root]=len[root]=0;
else
max_near[root]=max_l[root]=max_r[root]=len[root]=cr[root]-cl[root]+1;
return;
}
int m=(cr[root]+cl[root])>>1;
pushdown(root,root<<1,root<<1|1);
if(m>=l)
updata(l,r,root<<1,z);
if(m<r)
updata(l,r,root<<1|1,z);
pp(root);
}
int qian(int x)
{
if(cl[x<<1])
qian(x<<1);
if(cl[x<<1|1])
qian(x<<1|1);
}
int main()
{
scanf("%d%d",&n,&m);
build(1,1,n);
for(re i=1;i<=m;i++)
{
scanf("%d",&a);
if(a==1)
{
scanf("%d",&d);
if(max_near[1]<d)
{
printf("0\n");
continue;
}
o=que(1,d);
printf("%d\n",o);
updata(o,o+d-1,1,1);
}
else
{
scanf("%d%d",&x,&d);
updata(x,x+d-1,1,0);
}
}
return 0;
}