样例和input都过了还是0pts,寻遍了认识的巨佬都调不出来……
查看原帖
样例和input都过了还是0pts,寻遍了认识的巨佬都调不出来……
817925
whileAK楼主2023/8/15 15:58

蒟蒻尝试的第二道紫题,至今快一个月了吧,还是0pts,故在此征求天下巨佬的意见,助我A掉线段树题单对线段树有更深的理解~~

#include<bits/stdc++.h>
using namespace std;
int n,q,a[100005];
struct tree { //sum:1的数量 l0:连续前缀0的长度 l1同理;r则为后缀长度;
	int ll,rr,sum,l0,l1,r0,r1,max0,max1,s,fan;//max0为最长连续0的长度,max1同理,s表示是否有覆盖操作,fan表示是否有区间取反
} t[400005];
void push_up(int p) {
	int mid=t[p].ll+t[p].rr>>1,l=t[p].ll,r=t[p].rr;
	t[p].sum=t[2*p].sum+t[2*p+1].sum;//父子节点转移
	t[p].l0=t[2*p].l0;
	if(t[p].l0==mid-l+1)t[p].l0+=t[2*p+1].l0;
	t[p].l1=t[2*p].l1;
	if(t[p].l1==mid-l+1)t[p].l1+=t[2*p+1].l1;
	t[p].r0=t[2*p+1].r0;
	if(t[p].r0==r-mid)t[p].r0+=t[2*p].r0;
	t[p].r1=t[2*p+1].r1;
	if(t[p].r1==r-mid)t[p].r1+=t[2*p].r1;
	t[p].max0=max(t[2*p].max0,t[2*p+1].max0);
	t[p].max0=max(t[p].max0,t[2*p].r0+t[2*p+1].l0);
	t[p].max1=max(t[2*p].max1,t[2*p+1].max1);
	t[p].max1=max(t[p].max1,t[2*p].r1+t[2*p+1].l1);
}//建树
void build(int l,int r,int p) {
	t[p].ll=l,t[p].rr=r;
	t[p].s=-1,t[p].fan=0;
	if(l==r) {
		t[p].sum=a[l];
		t[p].l0=t[p].max0=t[p].l1=t[p].max1=t[p].r0=t[p].r1=0;
		if(a[l]==0)t[p].l0=t[p].max0=t[p].r0=1;
		else t[p].l1=t[p].max1=t[p].r1=1;
		return;
	}
	int mid=l+r>>1;
	build(l,mid,2*p),build(mid+1,r,2*p+1);
	push_up(p);
}
void spread(int p) { //懒标记传递
	int x=t[2*p].ll,y=t[2*p].rr,c=t[2*p+1].ll,d=t[2*p+1].rr;
	if(t[p].s!=-1) {
		t[2*p].sum=t[p].s*(y-x+1);
		t[2*p+1].sum=t[p].s*(d-c+1);
		if(!t[p].s)t[2*p].l0=t[2*p].r0=t[2*p].max0=y-x+1,t[2*p].l1=t[2*p].r1=t[2*p].max1=0;
		else t[2*p].l0=t[2*p].r0=t[2*p].max0=0,t[2*p].l1=t[2*p].r1=t[2*p].max1=y-x+1;
		if(!t[p].s)t[2*p+1].l0=t[2*p+1].r0=t[2*p+1].max0=d-c+1,t[2*p+1].l1=t[2*p+1].r1=t[2*p+1].max1=0;
		else t[2*p+1].l0=t[2*p+1].r0=t[2*p+1].max0=0,t[2*p+1].l1=t[2*p+1].r1=t[2*p+1].max1=d-c+1;
		t[2*p].s=t[2*p+1].s=t[p].s;
		t[p].s=-1;
	}
	if(t[p].fan) {
		t[2*p].sum=x-y+1-t[2*p].sum;
		t[2*p+1].sum=d-c+1-t[2*p+1].sum;
		swap(t[2*p].l0,t[2*p].l1);
		swap(t[2*p].r0,t[2*p].r1);
		swap(t[2*p].max0,t[2*p].max1);
		swap(t[2*p+1].l0,t[2*p+1].l1);
		swap(t[2*p+1].r0,t[2*p+1].r1);
		swap(t[2*p+1].max0,t[2*p+1].max1);
		if(t[2*p].s!=-1)t[2*p].s^=1;
		else t[2*p].fan^=1;
		if(t[2*p+1].s!=-1)t[2*p+1].s^=1;
		else t[2*p+1].fan^=1;
		t[p].fan=0;
	}
}
void mend01(int l,int r,int z,int p) { //覆盖操作
	spread(p);
	if(t[p].ll>=l&&t[p].rr<=r) {
		t[p].sum=z*(t[p].rr-t[p].ll+1);
		if(!z) t[p].l0=t[p].r0=t[p].max0=t[p].rr-t[p].ll+1,t[p].l1=t[p].r1=t[p].max1=0;
		else t[p].l0=t[p].r0=t[p].max0=0,t[p].l1=t[p].r1=t[p].max1=t[p].rr-t[p].ll+1;
		t[p].s=z;
		t[p].fan=0;
		return;
	}
	int mid=t[p].ll+t[p].rr>>1;
	if(l<=mid)mend01(l,r,z,2*p);
	if(r>mid)mend01(l,r,z,2*p+1);
	push_up(p);
}
void mend_fan(int l,int r,int p) { //取反操作
	spread(p);
	if(t[p].ll>=l&&t[p].rr<=r) {
		t[p].sum=t[p].rr-t[p].ll+1-t[p].sum;
		swap(t[p].l0,t[p].l1);
		swap(t[p].r0,t[p].r1);
		swap(t[p].max0,t[p].max1);
		if(t[p].s!=-1)t[p].s^=1;
		else t[p].fan^1;
		return;
	}
	int mid=t[p].ll+t[p].rr>>1;
	if(l<=mid)mend_fan(l,r,2*p);
	if(r>mid)mend_fan(l,r,2*p+1);
	push_up(p);
}
int find_sum(int l,int r,int p) {
	spread(p);
	if(t[p].ll>=l&&t[p].rr<=r) {
		return t[p].sum;
	}
	int mid=t[p].ll+t[p].rr>>1,ans=0;
	if(l<=mid)ans+=find_sum(l,r,2*p);
	if(r>mid)ans+=find_sum(l,r,2*p+1);
	return ans;
}
int find_l1(int l,int r,int p) { //查询l~r的连续前缀1的长度
	spread(p);
	if(t[p].ll>=l&&t[p].rr<=r) { //cout<<"l1:"<<t[p].ll<<" r1:"<<t[p].rr<<" ans:"<<t[p].l1<<endl;
		return t[p].l1;
	}
	int mid=t[p].ll+t[p].rr>>1,ans=0;
	if(l<=mid) { //转移
		ans=find_l1(l,r,2*p);
		if(r>mid&&ans==mid-max(l,t[p].ll)+1)ans+=find_l1(l,r,2*p+1);
	} else ans+=find_l1(l,r,2*p+1); //cout<<"l1:"<<t[p].ll<<" r1:"<<t[p].rr<<" ans:"<<ans<<endl;
	return ans;
}
int find_r1(int l,int r,int p) { //查询l~r的连续后缀1的长度
	spread(p);
	if(t[p].ll>=l&&t[p].rr<=r) { //cout<<"ll0:"<<l<<" rr0:"<<r<<" ans:"<<t[p].r1<<endl;//cout<<"ll0:"<<t[p].ll<<" rr0:"<<t[p].rr<<endl;
		return t[p].r1;
	}
	int mid=t[p].ll+t[p].rr>>1,ans=0;
	if(r>mid) { //转移
		ans=find_r1(l,r,2*p+1);
		if(l<=mid&&ans==min(r,t[2*p+1].rr)-mid)ans+=find_r1(l,r,2*p);
	} else ans+=find_r1(l,r,2*p); //cout<<"l0:"<<l<<" r0:"<<r<<" ans:"<<ans<<endl;
	return ans;
}
int find_1(int l,int r,int p) { //查询最长连续1的长度
	spread(p);
	if(t[p].ll>=l&&t[p].rr<=r) { //cout<<"l:"<<t[p].ll<<" r:"<<t[p].rr<<" ans:"<<t[p].max1<<endl;
		return t[p].max1;
	}
	int mid=t[p].ll+t[p].rr>>1,ans=0,k;
	if(l<=mid) { //转移
		k=find_1(l,r,2*p);
		ans=max(ans,k);
	}
	if(r>mid) {
		k=find_1(l,r,2*p+1);
		ans=max(ans,k);
	}
	if(l<=mid&&r>mid) {
		int u=find_l1(mid+1,r,1),v=find_r1(l,mid,1);//cout<<"l1:"<<mid+1<<" r1:"<<t[p].rr<<" u:"<<u<<endl;
		ans=max(ans,u+v);//cout<<"l0:"<<t[p].ll<<" r0:"<<mid<<" v:"<<v<<endl;
	}//cout<<"l:"<<t[p].ll<<" r:"<<t[p].rr<<" ans:"<<ans<<endl;
	return ans;
}
int main() {
	scanf("%d%d",&n,&q);
	for(register int i(1); i<=n; ++i)scanf("%d",&a[i]);
	build(1,n,1);
	int op,x,y;
	while(q--) {
		scanf("%d%d%d",&op,&x,&y);
		++x,++y;//输入下标以0开始,所以++;
		if(op==0||op==1) {
			mend01(x,y,op,1);
		}
		if(op==2) {
			mend_fan(x,y,1);
		}
		if(op==3) {
			printf("%d\n",find_sum(x,y,1));
		}
		if(op==4) {
			printf("%d\n",find_1(x,y,1));
		}
	}
	return 0;
}
2023/8/15 15:58
加载中...