问题主要是在work函数部分
注释的是原版(用这个版本过了2个Subtask #1 和1个Subtask #0)
后来照着题解改了改过了
但不太明白 二分的范围 和 在前面特判的[L1,R1]中0的个数小于[L0,R0]中1的个数 为什么出了问题
#include<bits/stdc++.h>
using namespace std;
int const X=5e5+100;
int n,m,a[X],b[X],op,x,y,x0,yy0;
struct tree{
int L,R,tag,len;
//tag:0无操作 1被挖出 2已被填
int Lmax,Rmax,S; //0(脑洞)的长度
int ans; //1的个数
};
tree t[X<<2];
inline int ls(int x){
return x<<1;
}
inline int rs(int x){
return x<<1 | 1;
}
void build(int rt,int L,int R){ //建树
t[rt].L=L; t[rt].R=R; t[rt].tag=0;
t[rt].len=R-L+1;
if(L==R){
t[rt].ans=1;
t[rt].Lmax=t[rt].Rmax=t[rt].S=0;
return ;
}
int mid=(L+R)>>1;
build(ls(rt),L,mid);
build(rs(rt),mid+1,R);
t[rt].ans=(t[ls(rt)].ans+t[rs(rt)].ans);
return ;
}
void push_up(tree &rt,tree tL,tree tR){
rt.ans=tL.ans+tR.ans;
rt.S=max(tL.S,max(tR.S,tL.Rmax+tR.Lmax));
rt.Lmax=tL.Lmax;
if(tL.Lmax==tL.len){
rt.Lmax+=tR.Lmax;
}
rt.Rmax=tR.Rmax;
if(tR.Rmax==tR.len){
rt.Rmax+=tL.Rmax;
}
return ;
}
void f1(tree &rt){
rt.ans=0;
rt.S=rt.Lmax=rt.Rmax=rt.len;
rt.tag=1;
return ;
}
void push_down1(int rt){ //tag=1
t[rt].tag=0;
f1(t[ls(rt)]);
f1(t[rs(rt)]);
return ;
}
void f2(tree &rt){
rt.ans=rt.len;
rt.Lmax=rt.Rmax=rt.S=0;
rt.tag=2;
return ;
}
void push_down2(int rt){ //tag=2
t[rt].tag=0;
f2(t[ls(rt)]);
f2(t[rs(rt)]);
return ;
}
void change(int rt,int L,int R,int qL,int qR,int p){
//修改
//p=0,[qL,qR]都改为 0
//p=1,[qL,qR]都改为 1
if(qL<=L && R<=qR){
if(p==0){
f1(t[rt]);
}
else if(p==1){
f2(t[rt]);
}
return ;
}
if(t[rt].tag==1) push_down1(rt);
if(t[rt].tag==2) push_down2(rt);
int mid=(L+R)>>1;
if(qL<=mid){
change(ls(rt),L,mid,qL,qR,p);
}
if(mid+1<=qR){
change(rs(rt),mid+1,R,qL,qR,p);
}
push_up(t[rt],t[ls(rt)],t[rs(rt)]);
return ;
}
int query1(int rt,int L,int R,int qL,int qR){ //查询[qL,qR]中1的个数
if(qL<=L && R<=qR){
return t[rt].ans;
}
if(t[rt].tag==1) push_down1(rt);
if(t[rt].tag==2) push_down2(rt);
int mid=(L+R)>>1,res=0;
if(qL<=mid) res+=query1(ls(rt),L,mid,qL,qR);
if(mid+1<=qR) res+=query1(rs(rt),mid+1,R,qL,qR);
return res;
}
int query0(int rt,int L,int R,int qL,int qR){ //查询[qL,qR]中0的个数
if(qL<=L && R<=qR){
return t[rt].len-t[rt].ans;
}
if(t[rt].tag==1) push_down1(rt);
if(t[rt].tag==2) push_down2(rt);
int mid=(L+R)>>1,res=0;
if(qL<=mid) res+=query0(ls(rt),L,mid,qL,qR);
if(mid+1<=qR) res+=query0(rs(rt),mid+1,R,qL,qR);
return res;
}
tree query(int rt,int L,int R,int qL,int qR){ //查询最长的连续0长度
if(qL<=L && R<=qR){
return t[rt];
}
if(t[rt].tag==1) push_down1(rt);
if(t[rt].tag==2) push_down2(rt);
int mid=(L+R)>>1;
if(qL<=mid && mid+1<=qR){
tree A,B,res;
A=query(ls(rt),L,mid,qL,qR);
B=query(rs(rt),mid+1,R,qL,qR);
push_up(res,A,B);
return res;
}
else if(qR<=mid){
return query(ls(rt),L,mid,qL,qR);
}
else{
return query(rs(rt),mid+1,R,qL,qR);
}
}
/*void work(int rt,int L,int R,int L0,int R0,int L1,int R1){
int sum1=query1(1,1,n,L0,R0),sum0=query0(1,1,n,L1,R1);
if(sum1==0) return ;
if(sum1>=sum0){
change(1,1,n,L0,R0,0);
change(1,1,n,L1,R1,1);
return ;
}
int l=L1,r=R1,mid=(l+r)>>1;
while(l<r){
mid=(l+r)>>1;
if(sum1>=query0(1,1,n,L1,mid)){
l=mid+1;
}
else{
r=mid;
}
}
change(1,1,n,L0,R0,0);
change(1,1,n,L1,l,1);
return ;
}*/
void work(int rt,int L,int R,int L0,int R0,int L1,int R1){ //挖[L0,R0] 填[L1,R1]
int sum1=query1(1,1,n,L0,R0);
if(sum1==0) return ;
change(1,1,n,L0,R0,0);
int l=L1,r=R1+1,mid=(l+r)>>1;
while(l+1<r){
mid=(l+r)>>1;
if(sum1>=query0(1,1,n,L1,mid)){
l=mid;
}
else{
r=mid;
}
}
change(1,1,n,L1,l,1);
return ;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin>>n>>m;
build(1,1,n);
while(m--){
cin>>op>>x>>y;
if(op==0){
change(1,1,n,x,y,0);
}
else if(op==1){
cin>>x0>>yy0;
work(1,1,n,x,y,x0,yy0);
}
else{
cout<<query(1,1,n,x,y).S<<endl;
}
}
return 0;
} ```
谢谢