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 long
int 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));}
}