Evanyou Blog 彩带

线段树2

  洛谷上的模板,与一般的线段树没什么太大区别,只是区间操作多了一个乘上一个值,用两个标记数组,下推标记的时候记得先乘后加就ok了

  传送门,代码:

#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
using namespace std;

typedef long long ll;
const int N=1e5+7;
int n,m;
ll seg[N<<2],s1[N<<2],s2[N<<2],a[N],mod;

inline ll read()
{
    ll x=0; char ch=getchar(); bool flag=false;
    while( ch<'0' || ch>'9' ) {
        if( ch=='-' ) flag=true; ch=getchar();
    }
    while( ch>='0' && ch<='9' ) {
        x=x*10+ch-'0'; ch=getchar();
    }
    return flag ? -x : x;
}

inline void pushup(int rt)
{
    seg[rt]=(seg[ls]+seg[rs])%mod;
}

inline void pushdown(int l,int r,int rt,ll ln,ll rn)
{
    if( s1[rt]!=1 ) {
        seg[ls]=seg[ls]*s1[rt]%mod;
        seg[rs]=seg[rs]*s1[rt]%mod;
        s1[ls]=s1[ls]*s1[rt]%mod;
        s1[rs]=s1[rs]*s1[rt]%mod;
        s2[ls]=s2[ls]*s1[rt]%mod;
        s2[rs]=s2[rs]*s1[rt]%mod;
        s1[rt]=1;
    }
    if( s2[rt]!=0 ) {
        seg[ls]=(seg[ls]+s2[rt]*ln%mod)%mod;
        seg[rs]=(seg[rs]+s2[rt]*rn%mod)%mod;
        s2[ls]=(s2[ls]+s2[rt])%mod;
        s2[rs]=(s2[rs]+s2[rt])%mod;
        s2[rt]=0;
    }
}

void build(int l,int r,int rt)
{    
    s1[rt]=1;
    if( l==r ) { 
        seg[rt]=a[l]%mod; return ;
    }
    int mid=l+r>>1;
    build(l,mid,ls); build(mid+1,r,rs);
    pushup(rt);
}

void update(int l,int r,int rt,int L,int R,ll C,int type)
{
    if( L>r || l>R ) return;
    if( L<=l && r<=R ) {
        if( type==1 ) {
            seg[rt]=seg[rt]*C%mod;
            s1[rt]=s1[rt]*C%mod;
            s2[rt]=s2[rt]*C%mod;
        } else {
            seg[rt]=(seg[rt]+C*(r-l+1))%mod;
            s2[rt]=(s2[rt]+C)%mod;
        }
        return;
    }
    int mid=l+r>>1;
    pushdown(l,r,rt,mid-l+1,r-mid);
    if( L<=mid ) update(l,mid,ls,L,R,C,type);
    if( R>mid ) update(mid+1,r,rs,L,R,C,type);
    pushup(rt);
}

ll query(int l,int r,int rt,int L,int R)
{
    if( L>r || R<l ) return 0;
    if( L<=l && r<=R ) return seg[rt];
    int mid=l+r>>1; ll ret=0;
    pushdown(l,r,rt,mid-l+1,r-mid);
    if( L<=mid ) ret=(ret+query(l,mid,ls,L,R))%mod;
    if( R>mid ) ret=(ret+query(mid+1,r,rs,L,R))%mod;
    return ret%mod;
}

int main()
{
    n=read(); m=read(); mod=read();
    for(int i=1; i<=n; ++i) a[i]=read();
    build(1,n,1);
    int s,x,y; ll z;
    for(int i=1; i<=m; ++i) {
        s=read();
        if( s==1 ) {
            x=read(), y=read(), z=read();
            update(1,n,1,x,y,z,1);
        } else if( s==2 ) {
            x=read(), y=read(), z=read();
            update(1,n,1,x,y,z,2);
        } else {
            x=read(), y=read();
            printf("%lld\n",query(1,n,1,x,y));
        }
    }
    return 0; 
}

 

貌似又是一道water题。。。

posted @ 2017-11-03 16:38  HolseLee  阅读(191)  评论(0编辑  收藏  举报