Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4952 Accepted Submission(s): 1452
#include<algorithm> #include<iostream> #include<string.h> #include<sstream> #include<stdio.h> #include<math.h> #include<vector> #include<string> #include<queue> #include<set> #include<map> using namespace std; const int INF=0x3f3f3f3f; const int maxn=100100; int sta[maxn<<2],ml0[maxn<<2],mr0[maxn<<2],ml1[maxn<<2];//sta为标记。ml1为1左端连续。ml0为0左端连续 int mr1[maxn<<2],ma1[maxn<<2],ma0[maxn<<2],one[maxn<<2];//ma1为最大1连续数.one记录1的个数 void opp(int L,int R,int k)//对于2操作。0和1互换 { swap(ma0[k],ma1[k]); swap(ml0[k],ml1[k]); swap(mr0[k],mr1[k]); one[k]=R-L-one[k]+1; } void pushup(int L,int R,int k)//下传标记 { int ls,rs,mid; ls=k<<1; rs=ls|1; mid=(L+R)>>1; ml0[k]=ml0[ls]; mr0[k]=mr0[rs]; ml1[k]=ml1[ls]; mr1[k]=mr1[rs]; if(ml0[ls]==mid-L+1) ml0[k]+=ml0[rs]; if(mr0[rs]==R-mid) mr0[k]+=mr0[ls]; if(ml1[ls]==mid-L+1) ml1[k]+=ml1[rs]; if(mr1[rs]==R-mid) mr1[k]+=mr1[ls]; ma1[k]=max(ma1[ls],ma1[rs]); ma1[k]=max(ma1[k],mr1[ls]+ml1[rs]); ma0[k]=max(ma0[ls],ma0[rs]); ma0[k]=max(ma0[k],mr0[ls]+ml0[rs]); one[k]=one[ls]+one[rs]; } void pushdown(int L,int R,int k)//上传 { int ls,rs,mid; ls=k<<1; rs=ls|1; mid=(L+R)>>1; //printf("mark %d->%d and %d->%d %d\n",L,mid,mid+1,R,sta[k]); if(sta[k]==0) { sta[ls]=sta[rs]=0; ma0[ls]=ml0[ls]=mr0[ls]=mid-L+1; ma1[ls]=ml1[ls]=mr1[ls]=one[ls]=ma1[rs]=ml1[rs]=mr1[rs]=one[rs]=0; ma0[rs]=ml0[rs]=mr0[rs]=R-mid; } else if(sta[k]==1) { sta[ls]=sta[rs]=1; ma0[ls]=ml0[ls]=mr0[ls]=ma0[rs]=ml0[rs]=mr0[rs]=0; ma1[ls]=ml1[ls]=mr1[ls]=one[ls]=mid-L+1; ma1[rs]=ml1[rs]=mr1[rs]=one[rs]=R-mid; } else { if(sta[ls]!=-1)//2操作对于0,1标记直接0,1标记互换 { if(sta[ls]==2)//原先有2直接变-1 sta[ls]=-1; else sta[ls]^=1; } else sta[ls]=2; if(sta[rs]!=-1) { if(sta[rs]==2) sta[rs]=-1; else sta[rs]^=1; } else sta[rs]=2; opp(L,mid,ls); opp(mid+1,R,rs); } sta[k]=-1; } void btree(int L,int R,int k) { int ls,rs,mid; sta[k]=-1; if(L==R) { scanf("%d",&one[k]); if(one[k]) { ma1[k]=ml1[k]=mr1[k]=1; ma0[k]=ml0[k]=mr0[k]=0; } else { ma1[k]=ml1[k]=mr1[k]=0; ma0[k]=ml0[k]=mr0[k]=1; } return ; } ls=k<<1; rs=ls|1; mid=(L+R)>>1; btree(L,mid,ls); btree(mid+1,R,rs); pushup(L,R,k); //printf("%d->%d\n",L,R); //printf("%d---%d----%d\n",ml1[k],mr1[k],one[k]); } void update(int L,int R,int l,int r,int k,int op) { int ls,rs,mid; if(l==L&&r==R) { if(op==0) { sta[k]=0; ma0[k]=ml0[k]=mr0[k]=R-L+1; ma1[k]=ml1[k]=mr1[k]=one[k]=0; } else if(op==1) { sta[k]=1; ma0[k]=ml0[k]=mr0[k]=0; ma1[k]=ml1[k]=mr1[k]=one[k]=R-L+1; } else { if(sta[k]==-1) sta[k]=2; else if(sta[k]==2) sta[k]=-1; else sta[k]^=1; opp(L,R,k); } //printf("mark %d->%d %d\n",L,R,op); //printf("%d->%d\n",L,R); //printf("%d---%d----%d\n",ml1[k],mr1[k],one[k]); return ; } if(sta[k]!=-1) pushdown(L,R,k); ls=k<<1; rs=ls|1; mid=(L+R)>>1; if(l>mid) update(mid+1,R,l,r,rs,op); else if(r<=mid) update(L,mid,l,r,ls,op); else { update(L,mid,l,mid,ls,op); update(mid+1,R,mid+1,r,rs,op); } pushup(L,R,k); //printf("%d->%d\n",L,R); //printf("%d---%d----%d\n",ml1[k],mr1[k],one[k]); } int qu(int L,int R,int l,int r,int k,int op) { int ls,rs,mid,tmp,ll,rr; if(sta[k]==0) return 0; if(sta[k]==1) return r-l+1; if(l==L&&r==R) { if(op==3) return one[k]; else return ma1[k]; } if(sta[k]!=-1) pushdown(L,R,k); ls=k<<1; rs=ls|1; mid=(L+R)>>1; if(l>mid) return qu(mid+1,R,l,r,rs,op); else if(r<=mid) return qu(L,mid,l,r,ls,op); else { if(op==3) return qu(L,mid,l,mid,ls,op)+qu(mid+1,R,mid+1,r,rs,op); else//4对于分离操作尤其注意!!最大值只能是以下几种情况。 { tmp=max(qu(L,mid,l,mid,ls,op),qu(mid+1,R,mid+1,r,rs,op));//最大值在左儿子或右儿子中 ll=max(mid-mr1[ls]+1,l);//最大值在中间区域 rr=min(mid+ml1[rs],r);//注意范围 tmp=max(tmp,rr-ll+1); return tmp; } } } int main() { int t,n,m,op,a,b; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); btree(1,n,1); while(m--) { scanf("%d%d%d",&op,&a,&b); a++,b++; if(op<3) update(1,n,a,b,1,op); else printf("%d\n",qu(1,n,a,b,1,op)); } } return 0; }