whileAK @ 2023-08-15 15:58:27
蒟蒻尝试的第二道紫题,至今快一个月了吧,还是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;
}
by whileAK @ 2023-08-15 15:59:31
码风不正,请见谅~
by JT_dw_ @ 2023-08-26 21:36:49
@whileAK 对拍造的数据:
6 6
0 0 1 1 1 0
2 3 6
4 1 4
1 1 4
0 3 4
3 2 2
2 5 6
out:
1
1
by whileAK @ 2023-08-27 18:14:58
也过了啊,还是0pts ……