求助
查看原帖
求助
398310
hundunqidian楼主2022/10/28 21:40

问题主要是在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;
}  ```
谢谢
2022/10/28 21:40
加载中...