Luogu_3373 (Double tag line segment tree template)

topic

https://www.luogu.org/problemnew/show/3373

Is to maintain a sequence, there are interval addition or multiplication operations, interval query.

analysis

  • The line segment tree has two kinds of tags, multiplication and addition, just push the formula for tag operation.
  • See the comments in the program for details.

program

#include <cstdio>
typedef long long ll;
ll n,m,Ha,k,k1,k2,k3;

struct segment_tree{
    #define X t[x]
    #define Lx (x<<1)
    #define Rx (Lx+1)
    #define L t[Lx]
    #define R t[Rx]
    #define Mid ((X.l+X.r)>>1)
    #define sz(x) (t[x].r-t[x].l+1)
    struct node{ll s,l,r,T1,T2;} t[2000000];        //[l,r]:  区间*t1+t2

    void mer(ll x){
        X.s=(L.s*L.T1+sz(Lx)*L.T2)%Ha;
        X.s=(X.s+R.s*R.T1+sz(Rx)*R.T2)%Ha;
    }

    void bui(ll x,ll l,ll r){
        X=(node){
   
   0,l,r,1,0};
        if (l==r) {scanf("%d",&X.s); return;}
        bui(Lx,l,Mid);
        bui(Rx,Mid+1,r);
        mer(x);
    }

    void add_tag(ll x,ll t1,ll t2){         //(x*T1+T2)*t1+t2=x*(T1*t1)+T2*t1+t2
        X.T1=(X.T1*t1)%Ha;
        X.T2=(X.T2*t1+t2)%Ha;
    }
    void down_tag(ll x){            //sigma(i*T1+T2)=sigma(i)*T1+sz*T2
        add_tag(Lx,X.T1,X.T2);
        add_tag(Rx,X.T1,X.T2);
        ll sz=X.r-X.l+1;
        X.s=(X.s*X.T1+sz*X.T2)%Ha;
        X.T1=1,X.T2=0;
    }

    ll que(ll x,ll l,ll r){     //询问 [l,r] 
        down_tag(x);
        if (l<=X.l && X.r<=r) return X.s;
        ll ret=0;
        if (l<=Mid) ret=(ret+que(Lx,l,r))%Ha;
        if (r>Mid) ret=(ret+que(Rx,l,r))%Ha;
        return ret;
    }

    void upd(ll x,ll l,ll r,ll t1,ll t2){   //[l,r]*t1+t2
        if (l<=X.l && X.r<=r){add_tag(x,t1,t2); return;}
        down_tag(x);
        if (l<=Mid) upd(Lx,l,r,t1,t2);
        if (r>Mid) upd(Rx,l,r,t1,t2);
        mer(x);
    }

} T;

int main(){
    scanf("%d%d%d",&n,&m,&Ha);
    T.bui(1,1,n);
    while (m--){
        scanf("%d",&k);
        if (k==1){
            scanf("%d%d%d",&k1,&k2,&k3);
            T.upd(1,k1,k2,k3,0);
            continue;
        }
        if (k==2){
            scanf("%d%d%d",&k1,&k2,&k3);
            T.upd(1,k1,k2,1,k3);
            continue;
        }
        scanf("%d%d",&k1,&k2);
        printf("%d\n",T.que(1,k1,k2));
    }
}

Guess you like

Origin blog.csdn.net/jackypigpig/article/details/78494778