考虑建立一棵线段树,维护:1.左端点的连续1和;2.右端点的连续1和;3.最长1的连续子序列;4.1的个数;5.将0和1交换后上面的四项;6.懒标记
具体实现中,需要注意细节,可以看代码(比较短)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 #define L (k<<1) 5 #define R (L+1) 6 #define mid (l+r>>1) 7 struct ji{ 8 int sum,ls,rs,ans; 9 }f0[N<<2],f1[N<<2]; 10 int n,m,p,x,y,laz[N<<2]; 11 ji merge(ji x,ji y){ 12 if (x.sum<0)return y; 13 if (y.sum<0)return x; 14 ji z; 15 z.sum=x.sum+y.sum; 16 z.ls=x.ls+((x.ls==x.sum)&&(x.rs==x.sum)&&(x.sum))*y.ls; 17 z.rs=y.rs+((y.rs==y.sum)&&(y.ls==y.sum)&&(y.sum))*x.rs; 18 z.ans=max(max(x.ans,y.ans),x.rs+y.ls); 19 return z; 20 } 21 int merge(int x,int y){ 22 if ((x<0)||(y<0))return x+y+1; 23 if ((x==2)&&(y==2))return -1; 24 if (x==2)return y^1; 25 return x; 26 } 27 void upd(int k,int l,int r,int x){ 28 if (x<0)return; 29 if (x<2){ 30 laz[k]=x; 31 f0[k].sum=f0[k].ls=f0[k].rs=f0[k].ans=(x^1)*(r-l+1); 32 f1[k].sum=f1[k].ls=f1[k].rs=f1[k].ans=x*(r-l+1); 33 return; 34 } 35 swap(f0[k],f1[k]); 36 if (laz[k]<0)laz[k]=2; 37 else 38 if (laz[k]>1)laz[k]=-1; 39 else laz[k]^=1; 40 } 41 void up(int k,int l,int r){ 42 f0[k]=merge(f0[L],f0[R]); 43 f1[k]=merge(f1[L],f1[R]); 44 upd(k,l,r,-1); 45 } 46 void down(int k,int l,int r){ 47 if (laz[k]<0)return; 48 upd(L,l,mid,laz[k]); 49 upd(R,mid+1,r,laz[k]); 50 laz[k]=-1; 51 } 52 void update(int k,int l,int r,int x,int y,int z){ 53 if ((l>y)||(x>r))return; 54 if ((x<=l)&&(r<=y)){ 55 upd(k,l,r,z); 56 return; 57 } 58 down(k,l,r); 59 update(L,l,mid,x,y,z); 60 update(R,mid+1,r,x,y,z); 61 up(k,l,r); 62 } 63 ji query(int k,int l,int r,int x,int y){ 64 if ((l>y)||(x>r))return ji{-1,0,0,0}; 65 if ((x<=l)&&(r<=y))return f1[k]; 66 down(k,l,r); 67 return merge(query(L,l,mid,x,y),query(R,mid+1,r,x,y)); 68 } 69 int main(){ 70 scanf("%d%d",&n,&m); 71 for(int i=1;i<=n;i++){ 72 scanf("%d",&x); 73 update(1,1,n,i,i,x); 74 } 75 for(int i=1;i<=m;i++){ 76 scanf("%d%d%d",&p,&x,&y); 77 x++,y++; 78 if (p<3)update(1,1,n,x,y,p); 79 else{ 80 ji o=query(1,1,n,x,y); 81 if (p==3)printf("%d ",o.sum); 82 if (p==4)printf("%d ",o.ans); 83 } 84 } 85 }