[BZOJ1858][SCOI2010]序列操作(线段树)
线段树维护区间内1的个数v,最长1/0连续段长度d1/0,从左端开始最长1/0连续段长度dl1/0,从右端开始最长1/0连续段长度dr1/0,区间覆盖标记和反转标记。
我的方法中覆盖标记和反转标记不能共存,当需要打覆盖标记时先清空反转标记,需要打反转标记时若当前已存在覆盖标记则变为打上相反的覆盖标记。
其余板子,注意build()时给标记设好初值。
1 #include<cstdio> 2 #include<algorithm> 3 #define ls (x<<1) 4 #define rs (ls|1) 5 #define lson ls,L,mid 6 #define rson rs,mid+1,R 7 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 8 using namespace std; 9 10 const int N=100010; 11 int n,m,l,r,op,a[N]; 12 struct Tr{ int v,l,r,ld1,rd1,ld0,rd0,d1,d0,tag,rev; }v[N<<2]; 13 14 Tr operator +(const Tr &a,const Tr &b){ 15 Tr c; c.l=a.l; c.r=b.r; 16 c.v=a.v+b.v; c.rev=0; c.tag=-1; 17 c.ld1=a.ld1+((a.ld1==a.r-a.l+1) ? b.ld1 : 0); 18 c.rd1=b.rd1+((b.rd1==b.r-b.l+1) ? a.rd1 : 0); 19 c.ld0=a.ld0+((a.ld0==a.r-a.l+1) ? b.ld0 : 0); 20 c.rd0=b.rd0+((b.rd0==b.r-b.l+1) ? a.rd0 : 0); 21 c.d1=max(max(a.d1,b.d1),a.rd1+b.ld1); 22 c.d0=max(max(a.d0,b.d0),a.rd0+b.ld0); 23 return c; 24 } 25 26 void put(int x,int k){ 27 if (k==-1){ 28 if (v[x].tag!=-1){ put(x,v[x].tag^1); return; } 29 v[x].rev^=1; v[x].v=(v[x].r-v[x].l+1)-v[x].v; 30 swap(v[x].ld1,v[x].ld0); swap(v[x].rd1,v[x].rd0); swap(v[x].d1,v[x].d0); 31 }else{ 32 v[x].rev=0; v[x].tag=k; 33 v[x].v=v[x].ld1=v[x].rd1=v[x].d1=k ? v[x].r-v[x].l+1 : 0; 34 v[x].ld0=v[x].rd0=v[x].d0=k ? 0 : v[x].r-v[x].l+1; 35 } 36 } 37 38 void push(int x){ 39 if (v[x].tag!=-1) put(ls,v[x].tag),put(rs,v[x].tag),v[x].tag=-1; 40 if (v[x].rev) put(ls,-1),put(rs,-1),v[x].rev=0; 41 } 42 43 void build(int x,int L,int R){ 44 v[x].l=L; v[x].r=R; v[x].tag=-1; 45 if (L==R){ 46 if (a[L]==1) v[x].v=v[x].ld1=v[x].rd1=v[x].d1=1,v[x].ld0=v[x].rd0=v[x].d0=0; 47 else v[x].v=v[x].ld1=v[x].rd1=v[x].d1=0,v[x].ld0=v[x].rd0=v[x].d0=1; 48 return; 49 } 50 int mid=(L+R)>>1; 51 build(lson); build(rson); v[x]=v[ls]+v[rs]; 52 } 53 54 void mdf(int x,int L,int R,int l,int r,int k){ 55 if (L==l && r==R){ put(x,k); return; } 56 int mid=(L+R)>>1; push(x); 57 if (r<=mid) mdf(lson,l,r,k); 58 else if (l>mid) mdf(rson,l,r,k); 59 else mdf(lson,l,mid,k),mdf(rson,mid+1,r,k); 60 v[x]=v[ls]+v[rs]; 61 } 62 63 Tr que(int x,int L,int R,int l,int r){ 64 if (L==l && r==R) return v[x]; 65 int mid=(L+R)>>1; push(x); 66 if (r<=mid) return que(lson,l,r); 67 else if (l>mid) return que(rson,l,r); 68 else return que(lson,l,mid)+que(rson,mid+1,r); 69 } 70 71 int main(){ 72 freopen("bzoj1858.in","r",stdin); 73 freopen("bzoj1858.out","w",stdout); 74 scanf("%d%d",&n,&m); 75 rep(i,1,n) scanf("%d",&a[i]); 76 build(1,1,n); 77 rep(i,1,m){ 78 scanf("%d%d%d",&op,&l,&r); l++; r++; 79 if (op==0) mdf(1,1,n,l,r,0); 80 if (op==1) mdf(1,1,n,l,r,1); 81 if (op==2) mdf(1,1,n,l,r,-1); 82 if (op==3) printf("%d\n",que(1,1,n,l,r).v); 83 if (op==4) printf("%d\n",que(1,1,n,l,r).d1); 84 } 85 return 0; 86 }