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