【AHOI2009】bzoj1798 维护序列

来源:互联网 发布:禁止程序联网软件 编辑:程序博客网 时间:2024/06/06 11:01

Description 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。 有长为N的数列,不妨设为a1,a2,…,aN
。有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值;
(3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。 Input
第一行两个整数N和P(1≤P≤1000000000)。第二行含有N个非负整数,从左到右依次为a1,a2,…,aN,
(0≤ai≤1000000000,1≤i≤N)。第三行有一个整数M,表示操作总数。从第四行开始每行描述一个操作,输入的操作有以下三种形式:
操作1:“1 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai×c (1≤t≤g≤N,0≤c≤1000000000)。
操作2:“2 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai+c (1≤t≤g≤N,0≤c≤1000000000)。
操作3:“3 t g”(不含双引号)。询问所有满足t≤i≤g的ai的和模P的值 (1≤t≤g≤N)。
同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。 Output
对每个操作3,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。

典型的线段树区间修改区间询问。
注意两个标记的顺序问题,即把每个结点强制看成x*m1+m2,这样的话标记乘法要同时标记加法,下传时也要先传乘法。
注意有乘0的情况。

#include<cstdio>#include<cstring>#define LL long longint m_p[1000010],m_t[1000010],sum[1000010],mod,n;void down(int p,int L,int R){    sum[p]=(LL)sum[p]*m_t[p]%mod;    m_p[p*2]=(LL)m_p[p*2]*m_t[p]%mod;    m_t[p*2]=(LL)m_t[p*2]*m_t[p]%mod;    m_p[p*2+1]=(LL)m_p[p*2+1]*m_t[p]%mod;    m_t[p*2+1]=(LL)m_t[p*2+1]*m_t[p]%mod;    sum[p]=(sum[p]+(LL)(R-L+1)*m_p[p])%mod;    m_p[p*2]=(m_p[p*2]+m_p[p])%mod;    m_p[p*2+1]=(m_p[p*2+1]+m_p[p])%mod;    m_t[p]=1;    m_p[p]=0;}void add(int p,int L,int R,int l,int r,int x){    down(p,L,R);    int i,j,k,M=(L+R)/2;    if (L==l&&R==r)    {        m_p[p]=(m_p[p]+x)%mod;        return;    }    if (r<=M)      add(p*2,L,M,l,r,x);    else    {        if (l>M)          add(p*2+1,M+1,R,l,r,x);        else        {            add(p*2,L,M,l,M,x);            add(p*2+1,M+1,R,M+1,r,x);        }    }    down(p*2,L,M);    down(p*2+1,M+1,R);    sum[p]=(sum[p*2]+sum[p*2+1])%mod;}void multi(int p,int L,int R,int l,int r,int x){    down(p,L,R);    int i,j,k,M=(L+R)/2;    if (L==l&&R==r)    {        m_p[p]=((LL)m_p[p]*x)%mod;        m_t[p]=((LL)m_t[p]*x)%mod;        return;    }    if (r<=M)      multi(p*2,L,M,l,r,x);    else    {        if (l>M)          multi(p*2+1,M+1,R,l,r,x);        else        {            multi(p*2,L,M,l,M,x);            multi(p*2+1,M+1,R,M+1,r,x);        }    }    down(p*2,L,M);    down(p*2+1,M+1,R);    sum[p]=(sum[p*2]+sum[p*2+1])%mod;}int qry(int p,int L,int R,int l,int r){    down(p,L,R);    int i,j,k,M=(L+R)/2;    if (L==l&&R==r)      return sum[p];    if (r<=M)      return qry(p*2,L,M,l,r);    if (l>M)      return qry(p*2+1,M+1,R,l,r);    return (qry(p*2,L,M,l,M)+qry(p*2+1,M+1,R,M+1,r))%mod;}int main(){    int i,j,k,m,n,x,y,z,w;    scanf("%d%d",&n,&mod);    for (i=1;i<=4*n;i++)      m_t[i]=1;    for (i=1;i<=n;i++)    {        scanf("%d",&x);        add(1,1,n,i,i,x);    }    scanf("%d",&m);    while (m--)    {        scanf("%d%d%d",&x,&y,&z);        if (x==1)        {            scanf("%d",&w);            multi(1,1,n,y,z,w);        }        if (x==2)        {            scanf("%d",&w);            add(1,1,n,y,z,w);        }        if (x==3) printf("%d\n",qry(1,1,n,y,z));    }}
0 0