洛谷 P2023 维护序列——线段树

先上一波题目 https://www.luogu.org/problem/P2023 

复习了一波线段树 题目涉及的操作有区间加 区间乘以及区间求和

tips:线段树在传标记的时候 优先传乘法标记再传加法标记 规定好顺序就不会错了

#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int M=200007;
LL read(){
    LL ans=0,f=1,c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
    return ans*f;
}
int n,L,R;
LL C,mod;
struct node{
    int l,r;
    LL ad,mx,sum;
}e[M*2];
void up(int x){e[x].sum=(e[x<<1].sum+e[x<<1^1].sum)%mod;}
void build(int x,int l,int r){
    e[x].l=l; e[x].r=r;
    e[x].ad=0; e[x].mx=1;
    if(l==r){e[x].sum=read()%mod; return ;}
    int mid=(l+r)>>1;
    build(x<<1,l,mid);
    build(x<<1^1,mid+1,r);
    up(x);
}
void down(int x){
    LL ad=e[x].ad,mx=e[x].mx;
    LL ls=x<<1,rs=x<<1^1,len1=e[ls].r-e[ls].l+1,len2=e[rs].r-e[rs].l+1;
    if(mx!=1){
        e[ls].sum=e[ls].sum*mx%mod;
        e[ls].ad=e[ls].ad*mx%mod;
        e[ls].mx=e[ls].mx*mx%mod;
        e[rs].sum=e[rs].sum*mx%mod;
        e[rs].ad=e[rs].ad*mx%mod;
        e[rs].mx=e[rs].mx*mx%mod;
        e[x].mx=1;
    }
    if(ad){
        e[ls].sum=(e[ls].sum+ad*len1%mod)%mod;
        e[ls].ad=(e[ls].ad+ad)%mod;
        e[rs].sum=(e[rs].sum+ad*len2%mod)%mod;
        e[rs].ad=(e[rs].ad+ad)%mod;
        e[x].ad=0;
    }
}
void dmx(int x){
    if(L<=e[x].l&&e[x].r<=R){
        e[x].sum=e[x].sum*C%mod;
        e[x].ad=e[x].ad*C%mod;
        e[x].mx=e[x].mx*C%mod;
        return ;
    }
    down(x);
    int mid=(e[x].l+e[x].r)>>1;
    if(L<=mid) dmx(x<<1);
    if(R>mid)  dmx(x<<1^1);
    up(x);
}
void dadd(int x){
    if(L<=e[x].l&&e[x].r<=R){
        LL len=e[x].r-e[x].l+1;
        e[x].sum=(e[x].sum+C*len%mod)%mod;
        e[x].ad=(e[x].ad+C)%mod;
        return ;
    }
    down(x);
    int mid=(e[x].l+e[x].r)>>1;
    if(L<=mid) dadd(x<<1);
    if(R>mid)  dadd(x<<1^1);
    up(x);
}
LL push(int x){
    if(L<=e[x].l&&e[x].r<=R) return e[x].sum;
    down(x);
    int mid=(e[x].l+e[x].r)>>1;
    LL ans=0;
    if(L<=mid) ans=(ans+push(x<<1))%mod;
    if(R>mid) ans=(ans+push(x<<1^1))%mod;
    up(x);
    return ans;
}
int k,m;
int main(){
    n=read(); mod=read();
    build(1,1,n);
    m=read();
    for(int i=1;i<=m;i++){
        k=read(); L=read(); R=read();
        if(k==1) C=read()%mod,dmx(1);
        else if(k==2) C=read()%mod,dadd(1);
        else printf("%lld\n",push(1));
    }
    return 0;
}
View Code

 

posted @ 2019-10-10 22:00  友人Aqaq  阅读(116)  评论(0)    收藏  举报