區間修改O(log2(n))
ll st[MAXN<<2],stmin[MAXN<<2],stvis[MAXN<<2],stmax[MAXN<<2];
ll a[MAXN];
void push_up(int rt)
{
stmax[rt]=max(stmax[lson],stmax[rson]);
stmin[rt]=min(stmin[lson],stmin[rson]);
st[rt]=st[lson]+st[rson];//修改位置
}
void push_down(int rt,int sec) //rt標記節點 sec區間
{
if(stvis[lson]==-1)
stvis[lson]=0;
stvis[lson]+=stvis[rt];
st[lson]+=stvis[rt]*(sec-(sec>>1));
stmin[lson]+=stvis[rt];
stmax[lson]+=stvis[rt];
if(stvis[rson]==-1)
stvis[rson]=0;
stvis[rson]+=stvis[rt];
st[rson]+=stvis[rt]*(sec>>1);
stmin[rson]+=stvis[rt];
stmax[rson]+=stvis[rt];
stvis[rt]=0;
}
void build(int l,int r,int rt)
{
stvis[rt]=0;
if(l==r)
{
stmax[rt]=stmin[rt]=st[rt]=a[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,lson);
build(mid+1,r,rson);
push_up(rt);
}
void update(int L,int R,ll v,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
stvis[rt]+=v;
st[rt]+=v*(r-l+1);
stmin[rt]+=v;
stmax[rt]+=v;
return;
}
if(stvis[rt])
push_down(rt,r-l+1);
int mid=(l+r)>>1;
if(L<=mid)
update(L,R,v,l,mid,lson);
if(mid<R)
update(L,R,v,mid+1,r,rson);
push_up(rt);
}
void mod_update(int L,int R,int mod,int l,int r,int rt)//區間mod
{
if(stmax[rt]<mod)
return;
if(l==r)
{
st[rt]%=mod;
stmax[rt]=st[rt];
return;
}
int mid=(l+r)>>1;
if(L<=mid)
mod_update(L,R,mod,l,mid,lson);
if(mid<R)
mod_update(L,R,mod,mid+1,r,rson);
push_up(rt);
}
ll query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return st[rt];
if(stvis[rt])
push_down(rt,r-l+1);
int mid=(l+r)>>1;
ll sum=0;
if(L<=mid)
sum+=query(L,R,l,mid,lson);//修改位置
if(mid<R)
sum+=query(L,R,mid+1,r,rson);//修改位置
return sum;
}
區間合併
ll stl_len[MAXN<<2],str_len[MAXN<<2],stall[MAXN<<2],stvis[MAXN<<2];
void push_up(int rt,int sec)
{
stl_len[rt]=stl_len[lson];
if(stl_len[rt]==sec-(sec>>1))//是否左兒子整個區間都是符合條件的
stl_len[rt]+=stl_len[rson];
str_len[rt]=str_len[rson];
if(str_len[rt]==(sec>>1))//是否右兒子整個區間都是符合條件的
str_len[rt]+=str_len[lson];
stall[rt]=max(str_len[lson]+stl_len[rson],max(stall[lson],stall[rson]));//左兒子的右區間與右兒子的左區間之和,左兒子的最長區間,右兒子的最長區間
}
void push_down(int rt,int sec)
{
stvis[lson]=stvis[rt];
stl_len[lson]=(sec-(sec>>1))*stvis[rt];
str_len[lson]=(sec-(sec>>1))*stvis[rt];
stall[lson]=(sec-(sec>>1))*stvis[rt];
stvis[rson]=stvis[rt];
stl_len[rson]=(sec>>1)*stvis[rt];
str_len[rson]=(sec>>1)*stvis[rt];
stall[rson]=(sec>>1)*stvis[rt];
stvis[rt]=-1;
}
void build(int l,int r,int rt)
{
stvis[rt]=-1;
if(l==r)
{
stl_len[rt]=1;
str_len[rt]=1;
stall[rt]=1;
return;
}
int mid=(l+r)>>1;
build(l,mid,lson);
build(mid+1,r,rson);
push_up(rt,r-l+1);
}
void update(int L,int R,ll v,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
stvis[rt]=v;
stl_len[rt]=(r-l+1)*v;
str_len[rt]=(r-l+1)*v;
stall[rt]=(r-l+1)*v;
return;
}
if(stvis[rt]!=-1)
push_down(rt,r-l+1);
int mid=(r+l)>>1;
if(L<=mid)
update(L,R,v,l,mid,lson);
if(mid<R)
update(L,R,v,mid+1,r,rson);
push_up(rt,r-l+1);
}
int query(int v,int l,int r,int rt)
{
if(l==r)
return l;
if(stvis[rt]!=-1)
push_down(rt,r-l+1);
int mid=(r+l)>>1;
if(stall[lson]>=v)
return query(v,l,mid,lson);
else if(str_len[lson]+stl_len[rson]>=v)
return mid-str_len[lson]+1;
else
return query(v,mid+1,r,rson);
}
區間異或
int stsum[MAXN<<2],stl_len[MAXN<<2][2],str_len[MAXN<<2][2],stall[MAXN<<2][2];
int stvis[MAXN<<2],stvis1[MAXN<<2];
int a[MAXN];
void change(int rt,int sec,int p)
{
if(p<2)
{
stall[rt][p]=stl_len[rt][p]=str_len[rt][p]=sec;
stall[rt][!p]=stl_len[rt][!p]=str_len[rt][!p]=0;
stsum[rt]=p>0?sec:0;
stvis[rt]=p;
}
else
{
swap(stall[rt][0],stall[rt][1]);
swap(stl_len[rt][0],stl_len[rt][1]);
swap(str_len[rt][0],str_len[rt][1]);
stsum[rt]=sec-stsum[rt];
stvis1[rt]^=1;
if(stvis[rt]!=-1)
stvis[rt]^=1;
}
}
void push_up(int rt,int sec)
{
stsum[rt]=stsum[lson]+stsum[rson];
for(int i=0;i<2;i++)
{
stl_len[rt][i]=stl_len[lson][i];
if(stl_len[rt][i]==sec-(sec>>1))
stl_len[rt][i]+=stl_len[rson][i];
str_len[rt][i]=str_len[rson][i];
if(str_len[rt][i]==(sec>>1))
str_len[rt][i]+=str_len[lson][i];
stall[rt][i]=max(stall[lson][i],stall[rson][i]);
stall[rt][i]=max(stall[rt][i],str_len[lson][i]+stl_len[rson][i]);
// cout<<"****"<<stl_len[rt][i]<<" "<<str_len[rt][i]<<" "<<stall[rt][i]<<endl<<endl;
}
// cout<<"*************"<<stsum[rt]<<endl<<endl;
}
void push_down(int rt,int sec)
{
if(stvis1[rt])
{
change(lson,sec-(sec>>1),2);
change(rson,sec>>1,2);
stvis1[rt]=0;
}
if(stvis[rt]!=-1)
{
change(lson,sec-(sec>>1),stvis[rt]);
change(rson,sec>>1,stvis[rt]);
stvis[rt]=-1;
}
}
void build(int l,int r,int rt)
{
stvis[rt]=-1,stvis1[rt]=0;
if(l==r)
{
stl_len[rt][a[l]]=str_len[rt][a[l]]=stall[rt][a[l]]=1;
stl_len[rt][!a[l]]=str_len[rt][!a[l]]=stall[rt][!a[l]]=0;
stsum[rt]=a[l]?1:0;
return;
}
int mid=(l+r)>>1;
build(l,mid,lson);
build(mid+1,r,rson);
push_up(rt,r-l+1);
}
void update(int L,int R,int p,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
change(rt,r-l+1,p);
return;
}
push_down(rt,r-l+1);
int mid=(l+r)>>1;
if(L<=mid)
update(L,R,p,l,mid,lson);
if(mid<R)
update(L,R,p,mid+1,r,rson);
push_up(rt,r-l+1);
}
int query(int L,int R,int p,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
if(p==3)
return stsum[rt];
else
return stall[rt][1];
}
push_down(rt,r-l+1);
int sum=0;
int mid=(l+r)>>1;
if(p==3)
{
if(L<=mid)
sum+=query(L,R,p,l,mid,lson);
if(mid<R)
sum+=query(L,R,p,mid+1,r,rson);
}
else
{
if(L<=mid)
sum=max(sum,query(L,R,p,l,mid,lson));
if(mid<R)
sum=max(sum,query(L,R,p,mid+1,r,rson));
sum=max(sum,min(str_len[lson][1],mid-L+1)+min(stl_len[rson][1],R-mid));
}
return sum;
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
build(1,n,1);
while(m--)
{
int op,c,b;
scanf("%d%d%d",&op,&c,&b);
c++,b++;
if(op<3)
update(c,b,op,1,n,1);
else
printf("%d\n",query(c,b,op,1,n,1));
}
}
}