线段树2(区间加和区间乘)

传送门

 

code:

#pragma GCC optimize("O3")
// #include<iostream>
#include<cstdio>
#include<cctype>
#define int long long
using namespace std;
#define ls(x) (x<<1)
#define rs(x) (ls(x)|1)
const int maxn=1e5+5;
struct FFF{
    int l,r;
    int sum;
    int add;
    int mul;
    int mid(){return l+r>>1;}
    int len(){return r-l+1;}
}t[maxn<<2];
int n,m,p;
char getc(){
    // return getchar();
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)? EOF:*p1++;
}
int read(){
    int s,f=1;
    char ch;
    while(!isdigit(ch=getc()))(ch=='-')&&(f=-1);
    for(s=ch-'0';isdigit(ch=getc());s=((s+(s<<2))<<1)+ch-'0');
    return s*f;
}
void build(int l=1,int r=n,int o=1){
    t[o].l=l;t[o].r=r;
    t[o].add=0;
    t[o].mul=1;
    if(l==r){
        (t[o].sum=read())%=p;
        return;
    }
    int mid=l+r>>1;
    build(l,mid,ls(o));
    build(mid+1,r,rs(o));
    t[o].sum=(t[ls(o)].sum+t[rs(o)].sum)%p;
}
void down(int o){
    int &v=t[o].add;
    int &f=t[o].mul;
    for(int i=0;i<=1;++i){
        t[ls(o)|i].add=(t[ls(o)|i].add*f)%p;
        t[ls(o)|i].sum=(t[ls(o)|i].sum*f)%p;
        t[ls(o)|i].mul=(t[ls(o)|i].mul*f)%p;
        t[ls(o)|i].add=(t[ls(o)|i].add+v)%p;
        t[ls(o)|i].sum=(t[ls(o)|i].sum+v*t[ls(o)|i].len())%p;
    }
    v=0;f=1;
}
void add(int l,int r,int v,int o=1){
    if(l<=t[o].l&&t[o].r<=r){
        (t[o].sum+=(v*t[o].len())%p)%=p;
        (t[o].add+=v)%=p;
        return;
    }
    int mid=t[o].mid();
    down(o);
    if(l<=mid)add(l,r,v,ls(o));
    if(r>mid)add(l,r,v,rs(o));
    t[o].sum=(t[ls(o)].sum+t[rs(o)].sum)%p;
}
void mul(int l,int r,int v,int o=1){
    if(l<=t[o].l&&t[o].r<=r){
        (t[o].sum*=v)%=p;
        (t[o].add*=v)%=p;
        (t[o].mul*=v)%=p;
        return;
    }
    int mid=t[o].mid();
    down(o);
    if(l<=mid)mul(l,r,v,ls(o));
    if(r>mid)mul(l,r,v,rs(o));
    t[o].sum=(t[ls(o)].sum+t[rs(o)].sum)%p;
}
int getsum(int l,int r,int o=1){
    if(l<=t[o].l&&t[o].r<=r){
        return t[o].sum%=p;
    }
    int ans=0;
    int mid=t[o].mid();
    down(o);
    if(l<=mid)(ans+=getsum(l,r,ls(o)))%=p;
    if(r>mid)(ans+=getsum(l,r,rs(o)))%=p;
    return ans%p;
}
signed main()
{
    n=read();m=read();p=read();
    build();
    while(m--){
        int op=read(),l=read(),r=read(),x;
        if(op==1){x=read();mul(l,r,x);}
        if(op==2){x=read();add(l,r,x);}
        if(op==3){printf("%lld\n",getsum(l,r));}
    }
    return 0;
}

  

posted @ 2018-08-04 20:18  kraylas  阅读(151)  评论(0编辑  收藏  举报