社区讨论

超级无敌难改的代码

学术版参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@lw28kiks
此快照首次捕获于
2024/05/11 23:03
2 年前
此快照最后确认于
2024/05/11 23:35
2 年前
查看原帖
对此,我无话可说
请大佬kankan
CPP
#include<bits/stdc++.h>
using namespace std;
const int N = 100007;
int n,m;
int mx[N*4][3],lmx[N*4][3],rmx[N*4][3]; 
int lz[N*4],sum[N*4],con[N*4];
void pushdown(int k,int l,int r,int mid){
	if(lz[k]!=-1){ 
		int v;
		lz[k*2]=lz[k*2+1]=lz[k];
		v=lz[k];
		sum[k*2]=v*(mid-l+1);
		sum[k*2+1]=v*(r-mid);
		mx[k*2][v]=lmx[k*2][v]=rmx[k*2][v]=mid-l+1;
		mx[k*2][v^1]=lmx[k*2][v^1]=rmx[k*2][v^1]=0;
		mx[k*2+1][v]=lmx[k*2+1][v]=rmx[k*2+1][v]=r-mid;
		mx[k*2+1][v^1]=lmx[k*2+1][v^1]=rmx[k*2+1][v^1]=0;
		lz[k]=-1;
		con[k]=con[k*2]=con[k*2+1]=0;
		return ;
	}
	if(con[k]){
		con[k*2]^=1;
		con[k*2+1]^=1;
		if(lz[k*2]!=-1) lz[k*2]^=1;
		if(lz[k*2+1]!=-1) lz[k*2+1]^=1;
		sum[k*2]=mid-l+1-sum[k*2];
		sum[k*2+1]=r-mid-sum[k*2+1];
		swap(mx[k*2][0],mx[k*2][1]);
		swap(lmx[k*2][0],lmx[k*2][1]);
		swap(rmx[k*2][0],rmx[k*2][1]);
		swap(mx[k*2+1][0],mx[k*2+1][1]);
		swap(lmx[k*2+1][0],lmx[k*2+1][1]);
		swap(rmx[k*2+1][0],rmx[k*2+1][1]);
		con[k]=0;
		return ;
	} 
	return ;
}

void pushup(int k,int l,int r,int mid){
	sum[k]=sum[k*2]+sum[k*2+1];
	for(int i=0;i<2;i++){
		lmx[k][i]=lmx[k*2][i];
		rmx[k][i]=rmx[k*2+1][i];
		if(sum[k*2] == i * (mid - l + 1)){
            lmx[k][i] += lmx[k*2+1][i];
        }
        if(sum[k*2+1] == i * (r - mid)){
            rmx[k][i] += rmx[k*2][i];
        }
        mx[k][i]=lmx[k*2+1][i]+rmx[k*2][i];
        mx[k][i] = max(mx[k][i], mx[k<<1][i]);
        mx[k][i] = max(mx[k][i], mx[k<<1|1][i]);
	}
}

void pushup_shi(int rt, int l, int r,int mid)
{
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    for(int i = 0; i < 2; ++i){
        lmx[rt][i] = lmx[rt<<1][i];
        if(sum[rt<<1] == i * (mid - l + 1)){
            lmx[rt][i] += lmx[rt<<1|1][i];
        }
        rmx[rt][i] = rmx[rt<<1|1][i];
        if(sum[rt<<1|1] == i * (r - mid)){
            rmx[rt][i] += rmx[rt<<1][i];
        }
        mx[rt][i] = rmx[rt<<1][i] + lmx[rt<<1|1][i];
        mx[rt][i] = max(mx[rt][i], mx[rt<<1][i]);
        mx[rt][i] = max(mx[rt][i], mx[rt<<1|1][i]);
    }
    return;
}
void build(int k,int l,int r){
	lz[k]=-1;
	con[k]=0;
	if(l==r){
		int v;
		scanf("%d",&v);
		sum[k]=v;
		mx[k][v]=1;
		lmx[k][v]=1;
		rmx[k][v]=1;
		return ;
	}
	int mid=(l+r)/2;
	build(k*2,l,mid);
	build(k*2+1,mid+1,r);
	pushup(k,l,r,mid);
}

void modify(int k,int l,int r,int x,int y,int opt){
	if(x<=l and r<=y){
		if(opt<=1){
			lz[k]=opt;
			con[k]=0;
			sum[k]=opt*(r-l+1);
			mx[k][opt]=lmx[k][opt]=rmx[k][opt]=r-l+1;
			mx[k][opt^1]=lmx[k][opt^1]=rmx[k][opt^1]=0;
			return ;
		}else{
			con[k]^=1;
			if(lz[k]!=-1) lz[k]^=1;
			sum[k]=r-l+1-sum[k];
			swap(mx[k][0],mx[k][1]);
			swap(lmx[k][0],lmx[k][1]);
			swap(rmx[k][0],rmx[k][1]);
			return ;
		}
	}
	int mid=(l+r)/2;
	pushdown(k,l,r,mid);
	if(x<=mid) modify(k*2,l,mid,x,y,opt);
	if(mid<y) modify(k*2+1,mid+1,r,x,y,opt);
	pushup(k,l,r,mid);
	return ;
}

int query(int k,int l,int r,int x,int y,int opt){
	if(x<=l and r<=y){
		if(opt==3) return sum[k];
		else return mx[k][1];
	}
	int mid=(l+r)/2,ans=0;
	pushdown(k,l,r,mid);
	if(x<=mid){
		if(opt==3){
			ans+=query(k*2,l,mid,x,y,opt);
		}else{
			ans=max(ans,query(k*2,l,mid,x,y,opt));
		}
	}
	if(mid<y){
		if(opt==3){
			ans+=query(k*2+1,mid+1,r,x,y,opt);
		}else{
			ans=max(ans,query(k*2+1,mid+1,r,x,y,opt));
		}
	}
	if(opt == 4 && x <= mid && mid < y){
        int tl = min(mid - x + 1, rmx[k*2][1]);
        int tr = min(y - mid, lmx[k*2+1][1]);
        ans = max(ans, tl + tr);
    }
	pushup(k,l,r,mid);
	return ans;
}
int main(){
	scanf("%d%d",&n,&m);
	build(1,0,n-1);
	while(m--){
		int opt,l,r;
		cin>>opt>>l>>r;
		if(opt<3) modify(1,0,n-1,l,r,opt);
		else printf("%d\n",query(1,0,n-1,l,r,opt));
	}
	return 0;
}
/*
lazy标记该区间是否整个被赋值
con标记该区间是否被反转
sum标记该区间1的个数
mx0/1标记该区间最多的连续0/1个数
lmx0/1标记该区间从左端点开始最多的连续的0/1个数
rmx0/1标记该区间从右端点开始最多的连续的0/1个数
*/

回复

0 条回复,欢迎继续交流。

正在加载回复...