【区间维护】线段树统计(染色细胞版)

经典线段树,区间修改,区间查询,比较麻烦

#include<bits/stdc++.h>
using namespace std;
#define N 1000005 
void read(int &x){
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}
int n,m;
int a[N];
struct node{
    int l,r,lazy,cnt,Left,Right;
    #define l(x) tree[x].l
    #define r(x) tree[x].r
    #define lazy(x) tree[x].lazy
    #define cnt(x) tree[x].cnt
    #define Left(x) tree[x].Left
    #define Right(x) tree[x].Right
}tree[N<<2];
void PushUp(int p){
    cnt(p)=cnt(2*p)+cnt(2*p+1)-(Right(p*2)==Left(p*2+1)); 
    Left(p)=Left(p*2);
    Right(p)=Right(p*2+1);
}
void PushDown(int p){
    if(lazy(p)){
        lazy(p*2)=lazy(p*2+1)=lazy(p);
        Left(p*2)=Right(p*2)=Left(p*2+1)=Right(p*2+1)=lazy(p);
        cnt(p*2)=cnt(p*2+1)=1;
        lazy(p)=0;
    }
}
void Build(int p,int l,int r){
    l(p)=l,r(p)=r;
    if(l==r){
        Left(p)=Right(p)=a[l];
        cnt(p)=1;
        return;
    }
    int mid=(l+r)>>1;
    Build(p*2,l,mid);
    Build(p*2+1,mid+1,r);
    PushUp(p);
}
void Update(int p,int l,int r,int val){
    if(l<=l(p)&&r>=r(p)){
        lazy(p)=val;
        Left(p)=Right(p)=val;
        cnt(p)=1;
        return;
    }
    PushDown(p);
    int mid=(l(p)+r(p))>>1;
    if(l<=mid) Update(p*2,l,r,val);
    if(r>mid) Update(p*2+1,l,r,val);
    PushUp(p);
}
int Query(int p,int l,int r){
    if(l<=l(p)&&r>=r(p)) return cnt(p);
    PushDown(p);
    int mid=(l(p)+r(p))>>1;
    int ret=0;
    if(l<=mid) ret=Query(p*2,l,r);
    if(r>mid) ret+=Query(p*2+1,l,r)-(ret&&Right(p*2)==Left(p*2+1));
    return ret; 
}
int main(){
    read(n),read(m);
    for(int i=1;i<=n;++i)
        read(a[i]);
    Build(1,1,n);
    while(m--){
        int c,x,y,z;
        read(c);
        read(x),read(y);
        if(x>y) swap(x,y);
        if(c==1){
            read(z);
            Update(1,x,y,z);
        }else{
            int ans=Query(1,x,y);
            printf("%d\n",ans);
        }
        /*for(int i=1;i<=n*2;++i){
            //printf("%d %d %d %d %d %d\n",l(i),r(i),Left(i),Right(i),cnt(i),i);
        }*/
    }
    return 0;
}

 

posted @ 2022-02-13 11:00  LikC1606  阅读(74)  评论(0)    收藏  举报