洛谷 P3373 线段树2

洛谷 P3373 线段树2 

mul和pls更新某区间左右子树sum的时候,别忘了回头更新这个区间的sum

只有在传递给子序列之后,父序列的lz标记才能清零。其他时候,lz标记只增不减

#include <stdlib.h>
#include <cstdio>
#include <iostream>
#include <queue>
#include <stack>
#include <string.h>
#include <math.h>
#include <algorithm>

#define mem(t, v)   memset ((t) , v, sizeof(t))
#define INF 0x3f3f3f3f
#define eps 1e-8
typedef long long ll;

using namespace std;


const int MAX=100010;
ll n,m,a,x,y,k,p;
ll in[MAX];

struct node{
    ll sum,l,r,plz,mlz;
}tree[MAX*4];

void Build(ll i,ll l,ll r){
    tree[i].r=r,tree[i].l=l;
    tree[i].mlz=1;
    if(l==r){
        tree[i].sum=in[l]%p;
        tree[i].plz=0;
        return ;
    }
    ll mid=(l+r)>>1;
    Build(i<<1,l,mid);
    Build(i<<1|1,mid+1,r);
    tree[i].sum=(tree[i<<1].sum+tree[i<<1|1].sum)%p;
}

inline void push_down(ll i){
    ll k1=tree[i].mlz,k2=tree[i].plz;
    tree[i].plz=0;
    tree[i].mlz=1;
    tree[i<<1].sum=(tree[i<<1].sum*k1+(tree[i<<1].r-tree[i<<1].l+1)*k2)%p;
    tree[i<<1|1].sum=(tree[i<<1|1].sum*k1+(tree[i<<1|1].r-tree[i<<1|1].l+1)*k2)%p;
    tree[i<<1].mlz=(tree[i<<1].mlz*k1)%p;
    tree[i<<1].plz=(tree[i<<1].plz*k1+k2)%p;
    tree[i<<1|1].mlz=(tree[i<<1|1].mlz*k1)%p;
    tree[i<<1|1].plz=(tree[i<<1|1].plz*k1+k2)%p;
}

void mul(ll i,ll l,ll r,ll k){   //对于标记,乘的时候只管乘,加的时候只管加
    if(tree[i].l>=l&&tree[i].r<=r){
        tree[i].sum=(tree[i].sum*k)%p;
        tree[i].mlz=(tree[i].mlz*k)%p;
        tree[i].plz=(tree[i].plz*k)%p;   //乘的时候已经把加标记处理了,所以后续都是先乘后加
        return ;
    }
    if(tree[i].r<l||tree[i].l>r)return ;
    push_down(i);
    if(tree[i<<1].r>=l)mul(i<<1,l,r,k);
    if(tree[i<<1|1].l<=r)mul(i<<1|1,l,r,k);
    tree[i].sum=(tree[i<<1].sum+tree[i<<1|1].sum)%p;
}

void pls(ll i,ll l,ll r,ll k){   //对于标记,乘的时候只管乘,加的时候只管加
    if(tree[i].l>=l&&tree[i].r<=r){
        tree[i].sum=(tree[i].sum+k*(tree[i].r-tree[i].l+1))%p;
        tree[i].plz=(tree[i].plz+k)%p;  //标记还是要加的,左右子树要用到
        return ;
    }
    if(tree[i].l>r||tree[i].r<l)return ;
    push_down(i);
    if(tree[i<<1].r>=l)pls(i<<1,l,r,k);
    if(tree[i<<1|1].l<=r)pls(i<<1|1,l,r,k);
    tree[i].sum=(tree[i<<1].sum+tree[i<<1|1].sum)%p;
}

ll Search(ll i,ll l,ll r){
    ll k1=tree[i].mlz,k2=tree[i].plz;
    if(tree[i].l>=l&&tree[i].r<=r){
        return tree[i].sum;
    }
    if(tree[i].l>r||tree[i].r<l)return 0;
    push_down(i);
    ll s=0;
    if(tree[i<<1|1].l<=r)s+=Search(i<<1|1,l,r);
    if(tree[i<<1].r>=l)s+=Search(i<<1,l,r);
    return s;
}

int main(){
    scanf("%lld%lld%lld",&n,&m,&p);
    for(int i=1;i<=n;i++){
        scanf("%lld",&in[i]);
    }

    Build(1,1,n);

    while(m--){
        scanf("%lld%lld%lld",&a,&x,&y);
        if(a==1){
            scanf("%lld",&k);
            mul(1,x,y,k);
        }
        else if(a==2){
            scanf("%lld",&k);
            pls(1,x,y,k);
        }
        else {
            ll ans=Search(1,x,y);
            printf("%lld\n",ans%p);
        }
    }
    return 0;
}
发布了62 篇原创文章 · 获赞 7 · 访问量 1636

猜你喜欢

转载自blog.csdn.net/qq_43331910/article/details/101099488
今日推荐