zoukankan      html  css  js  c++  java
  • [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
    ",que(1,1,n,l,r).v);
    83         if (op==4) printf("%d
    ",que(1,1,n,l,r).d1);
    84     }
    85     return 0;
    86 }
  • 相关阅读:
    winform 剔除空格与换行显示
    编码
    todo
    react高阶函数组件
    Docker-compose Setup for Self-hosting Development & Deployment Tools
    Self-hosting Sentry With Docker and Docker-compose
    how does Array.prototype.slice.call() work?
    todo reading
    a better git log
    https://coderwall.com/p/7smjkq/multiple-ssh-keys-for-different-accounts-on-github-or-gitlab
  • 原文地址:https://www.cnblogs.com/HocRiser/p/10579772.html
Copyright © 2011-2022 走看看