码迷,mamicode.com
首页 > 其他好文 > 详细

COGS.1272.[AHOI2009]行星序列(线段树 区间加、乘、求和)

时间:2018-02-12 15:10:52      阅读:153      评论:0      收藏:0      [点我收藏+]

标签:ble   for   线段树   class   stdout   etc   register   std   php   

题目链接

//注意取模! 
#include<cstdio>
#include<cctype>
using namespace std;
const int N=1e5+5;

int n,mod,Sum[N<<2],aTag[N<<2],mTag[N<<2];

inline int read()
{
    int now=0,f=1;register char c=getchar();
    for(;!isdigit(c);c=getchar())
      if(c=='-') f=-1;
    for(;isdigit(c);now=now*10+c-'0',c=getchar());
    return now*f;
}

inline void PushUp(int rt)
{
    Sum[rt]=(Sum[rt<<1]+Sum[rt<<1|1])%mod;
}
inline void PushDown(int m,int rt)
{
    if(mTag[rt]!=1)
    {
        mTag[rt<<1]=1ll*mTag[rt<<1]*mTag[rt]%mod;
        mTag[rt<<1|1]=1ll*mTag[rt<<1|1]*mTag[rt]%mod;
        aTag[rt<<1]=1ll*aTag[rt<<1]*mTag[rt]%mod;
        aTag[rt<<1|1]=1ll*aTag[rt<<1|1]*mTag[rt]%mod;
        Sum[rt<<1]=1ll*Sum[rt<<1]*mTag[rt]%mod;
        Sum[rt<<1|1]=1ll*Sum[rt<<1|1]*mTag[rt]%mod;
        mTag[rt]=1;
    }
    if(aTag[rt])
    {
        aTag[rt<<1]+=aTag[rt], aTag[rt<<1]%=mod;
        aTag[rt<<1|1]+=aTag[rt], aTag[rt<<1|1]%=mod;
        Sum[rt<<1]=(1ll*Sum[rt<<1]+1ll*(m-(m>>1))*aTag[rt]%mod)%mod;
        Sum[rt<<1|1]=(1ll*Sum[rt<<1|1]+1ll*(m>>1)*aTag[rt]%mod)%mod;
        aTag[rt]=0;
    }
}
void Build(int l,int r,int rt)
{
    mTag[rt]=1;
    if(l==r)
    {
        Sum[rt]=read()%mod;
        return;
    }
    int m=l+r>>1;
    Build(l,m,rt<<1),Build(m+1,r,rt<<1|1);
    PushUp(rt);
}
void Modify_Add(int l,int r,int rt,int L,int R,int v)
{
    if(L<=l && r<=R)
    {
        aTag[rt]+=v;
        if(aTag[rt]>=mod) aTag[rt]-=mod;
        Sum[rt]=(1ll*Sum[rt]+1ll*v*(r-l+1))%mod;
        return;
    }
    PushDown(r-l+1,rt);
    int m=l+r>>1;
    if(L<=m) Modify_Add(l,m,rt<<1,L,R,v);
    if(m<R) Modify_Add(m+1,r,rt<<1|1,L,R,v);
    PushUp(rt);
}
void Modify_Mult(int l,int r,int rt,int L,int R,int v)
{
    if(L<=l && r<=R)
    {
        aTag[rt]=1ll*aTag[rt]*v%mod;
        mTag[rt]=1ll*mTag[rt]*v%mod;
        Sum[rt]=1ll*Sum[rt]*v%mod;
        return;
    }
    PushDown(r-l+1,rt);
    int m=l+r>>1;
    if(L<=m) Modify_Mult(l,m,rt<<1,L,R,v);
    if(m<R) Modify_Mult(m+1,r,rt<<1|1,L,R,v);
    PushUp(rt);
}
int Query_Sum(int l,int r,int rt,int L,int R)
{
    if(L<=l && r<=R) return Sum[rt];
    PushDown(r-l+1,rt);
    int m=l+r>>1;long long res=0;
    if(L<=m) res+=Query_Sum(l,m,rt<<1,L,R), res%=mod;
    if(m<R) res+=Query_Sum(m+1,r,rt<<1|1,L,R), res%=mod;
    return res;
}

int main()
{
    freopen("seqb.in","r",stdin);
    freopen("seqb.out","w",stdout);

    n=read(),mod=read();
    Build(1,n,1);
    int m=read(),opt,l,r,v;
    while(m--)
    {
        opt=read(),l=read(),r=read();
        if(opt==1)
            v=read(), Modify_Mult(1,n,1,l,r,v);
        else if(opt==2)
            v=read(), Modify_Add(1,n,1,l,r,v);
        else
            printf("%d\n",Query_Sum(1,n,1,l,r));
    }

    fclose(stdin);fclose(stdout);
    return 0;
}

COGS.1272.[AHOI2009]行星序列(线段树 区间加、乘、求和)

标签:ble   for   线段树   class   stdout   etc   register   std   php   

原文地址:https://www.cnblogs.com/SovietPower/p/8444260.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!