均摊线段树上二分RE求调马蜂优附详细解释
查看原帖
均摊线段树上二分RE求调马蜂优附详细解释
547725
Zilljy258楼主2024/11/7 21:20
t是线段树
sm是子树和
sz是子树大小
lmax,rmax,mx分别是左边最长连续0,右边最长连续0,和区间内最长连续的0
chg区间修改
qrysum求区间和
qry用于求解2操作
efg是树上二分用于挖了一块脑洞后求填补在哪个区间

image.png

RE代码

#include<iostream>
#include<cstdio>

#define lo (nw<<1)
#define ro (nw<<1|1)
#define md (l+r>>1)

using namespace std;

int n,m;
struct Tree{
	int sm,sz;
	int lmx,rmx,mx;
	int ch;
}t[8000010]; 

void mkch(int nw,int z){
	t[nw].sm=z*t[nw].sz;
	t[nw].ch=z;
	if(z) t[nw].lmx=t[nw].rmx=t[nw].mx=0;
	else t[nw].lmx=t[nw].rmx=t[nw].mx=t[nw].sz;
	return ;
}

void upd(int nw){
	t[nw].sm=t[lo].sm+t[ro].sm;
	t[nw].sz=t[lo].sz+t[ro].sz;
	
	if(t[lo].lmx==t[lo].sz){
		t[nw].lmx=t[lo].lmx+t[ro].lmx;
	}
	else{
		t[nw].lmx=t[lo].lmx;
	}
	
	if(t[ro].rmx==t[ro].sz){
		t[nw].rmx=t[ro].rmx+t[lo].rmx;
	}
	else{
		t[nw].rmx=t[ro].rmx;
	}
	
	t[nw].mx=max(t[lo].rmx+t[ro].lmx,max(t[lo].mx,t[ro].mx));
	
	return ;
}

void psd(int nw){
	if(t[nw].ch!=-1){
		mkch(lo,t[nw].ch);
		mkch(ro,t[nw].ch);
		t[nw].ch=-1;
	}
	return ;
}

void bld(int nw,int l,int r){
	t[nw].ch=-1;
	t[nw].lmx=t[nw].mx=t[nw].rmx=0;
	if(l==r){
		t[nw].sm=t[nw].sz=1;
		return ;
	}
	bld(lo,l,md);
	bld(ro,md+1,r);
	upd(nw);
	return ;
}

void chg(int nw,int l,int r,int x,int y,int z){
//	if(l==r){
//		mkch(nw,z);
//		return ;
//	}
//	cout<<nw<<" "<<l<<" "<<r<<endl;
	if(x<=l&&r<=y){
		mkch(nw,z);
		return ;
	}
	
//	cout<<nw<<" "<<t[nw].sm<<" "<<t[lo].sm<<" "<<t[ro].sm<<" "<<t[nw].ch<<endl;
	psd(nw);
	if(x<=md) chg(lo,l,md,x,y,z);
	if(y>md) chg(ro,md+1,r,x,y,z);
	upd(nw);
//	cout<<nw<<" "<<t[nw].sm<<" "<<t[lo].sm<<" "<<t[ro].sm<<endl;
	
	return ;
}

int qry(int nw,int l,int r,int x,int y){
	if(x<=l&&r<=y){
		return t[nw].mx;
	}
	
	psd(nw);
	if(y<=md) return qry(lo,l,md,x,y);
	if(x>md) return qry(ro,md+1,r,x,y);
	return max(max(qry(lo,l,md,x,y),qry(ro,md+1,r,x,y)),min(t[lo].rmx,md+1-x)+min(t[ro].lmx,y-md));
}

int qrysum(int nw,int l,int r,int x,int y){
	if(x<=l&&r<=y){
		return t[nw].sm;
	}
	
	psd(nw);
	int ans=0;
	if(x<=md) ans+=qrysum(lo,l,md,x,y);
	if(y>md) ans+=qrysum(ro,md+1,r,x,y);
	return ans;
}

void efg(int nw,int l,int r,int x,int y,int z){
	if(x<=l&&r<=y&&z>=r-l+1-t[nw].sm){
		chg(1,1,n,l,r,1);
		return ;
	}
	
	psd(nw);
	int num=md-x+1-qrysum(1,1,n,x,md);
	if(x<=md){
		efg(lo,l,md,x,y,z);
		z-=num;
		if(y>md&&z>0){
			efg(ro,md+1,r,x,y,z);
		}
	}
	else if(y>md){
		efg(ro,md+1,r,x,y,z);
	}
	upd(nw);
	return ;
}

int main(){
	scanf("%d%d",&n,&m);
	bld(1,1,n);
	int op,l,r,ll,rr,num;
//	for(int i=1;i<=4*n;++i){
//		cout<<t[i].sm<<" ";
//	}
//	cout<<endl;
	for(int i=1;i<=m;++i){
		scanf("%d%d%d",&op,&l,&r);
		if(op==0){
//	cout<<1<<endl;
			chg(1,1,n,l,r,0);
		}
		if(op==1){
			scanf("%d%d",&ll,&rr);
			num=qrysum(1,1,n,l,r);
//			cout<<num<<endl;
			chg(1,1,n,l,r,0);
//			for(int i=1;i<=4*n;++i){
//			cout<<t[i].sm<<" ";
//		}
//		cout<<endl;
			efg(1,1,n,ll,rr,num);
		}
		if(op==2){
			printf("%d\n",qry(1,1,n,l,r));
		}
			
//		for(int i=1;i<=4*n;++i){
//			cout<<t[i].sm<<" ";
//		}
//		cout<<endl;
	}
	return 0;
}
2024/11/7 21:20
加载中...