题目描述
原题来自:AHOI 2009
老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。
有长为 nn 的数列,不妨设为 a_1,a_2,\cdots ,a_na1,a2,⋯,an。有如下三种操作形式:
- 把数列中的一段数全部乘一个值;
- 把数列中的一段数全部加一个值;
- 询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模 PP 的值。
输入格式
第一行两个整数 nn 和 PP;
第二行含有 nn 个非负整数,从左到右依次为 a_1,a_2,\cdots ,a_na1,a2,⋯,an;
第三行有一个整数 MM,表示操作总数;
从第四行开始每行描述一个操作,输入的操作有以下三种形式:
- 操作 11:
1 t g c
,表示把所有满足 t\le i\le gt≤i≤g 的 a_iai 改为 a_i\times cai×c; - 操作 22:
2 t g c
,表示把所有满足 t\le i\le gt≤i≤g 的 a_iai 改为 a_i+cai+c; - 操作 33:
3 t g
,询问所有满足 t\le i\le gt≤i≤g 的 a_iai 的和模 PP 的值。
同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。
输出格式
对每个操作 33,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。
样例
Inputcopy | Outputcopy |
---|---|
7 43 1 2 3 4 5 6 7 5 1 2 5 5 3 2 4 2 3 7 9 3 1 3 3 4 7 | 2 35 8 |
初始时数列为 {1,2,3,4,5,6,7}{1,2,3,4,5,6,7};
经过第 11 次操作后,数列为 {1,10,15,20,25,6,7}{1,10,15,20,25,6,7};
对第 22 次操作,和为 10+15+20=4510+15+20=45,模 4343 的结果是 22;
经过第 33 次操作后,数列为 {1,10,24,29,34,15,16}{1,10,24,29,34,15,16};
对第 44 次操作,和为 1+10+24=351+10+24=35,模 4343 的结果是 3535;
对第 55 次操作,和为 29+34+15+16=9429+34+15+16=94,模 4343 的结果是 88。
数据范围与提示
对于全部测试数据,1\le t\le g\le n,0\le c,a_i\le 10^9,1\le P\le 10^9+71≤t≤g≤n,0≤c,ai≤109,1≤P≤109+7。
测试数据规模如下表所示:
数据编号 | 111" style="text-align:center;">11 | 2,32,32,3" style="text-align:center;">2,32,3 | 444" style="text-align:center;">44 | 555" style="text-align:center;">55 | 666" style="text-align:center;">66 | 777" style="text-align:center;">77 | 888" style="text-align:center;">88 | 9,109,109,10" style="text-align:center;">9,109,10 |
---|---|---|---|---|---|---|---|---|
n=n= | 1010 | 10^3103 | 10^4104 | 6\times 10^46×104 | 7\times 10^47×104 | 8\times 10^48×104 | 9\times 10^49×104 | 10^5105 |
M=M= | 1010 | 10^3103 | 10^4104 | 6\times 10^46×104 | 7\times 10^47×104 | 8\times 10^48×104 |
取模运算性质:
(a + b) % p = (a % p + b % p) % p;
(a * b) % p = (a % p * b % p) % p;
取模:
#include<iostream>
using namespace std;
const int N=100000;
long long a[N*4+5];
long long n,p,m;
long long ans;
struct Node
{
long long len;
long long sum;
long long mflag;
long long flag;
}tree[4*N+5];
void pushdown(long rt)
{
if(tree[rt].flag!=0||tree[rt].mflag!=1)
{
tree[rt*2].flag=(tree[rt].mflag*tree[rt*2].flag+tree[rt].flag)%p;
tree[rt*2+1].flag=(tree[rt].mflag*tree[rt*2+1].flag+tree[rt].flag)%p;
tree[rt*2].mflag*=tree[rt].mflag;
tree[rt*2].mflag=tree[rt*2].mflag%p;
tree[rt*2+1].mflag*=tree[rt].mflag;
tree[rt*2+1].mflag=tree[rt*2+1].mflag%p;
tree[rt*2].sum=tree[rt*2].sum*tree[rt].mflag%p+tree[rt].flag*tree[rt*2].len%p;
tree[rt*2].sum=tree[rt*2].sum%p;
tree[rt*2+1].sum=tree[rt*2+1].sum*tree[rt].mflag%p+tree[rt].flag*tree[rt*2+1].len%p;
tree[rt*2+1].sum=tree[rt*2+1].sum%p;
tree[rt].flag=0;
tree[rt].mflag=1;
}
}
void pushup(long rt)
{
tree[rt].sum=tree[rt*2].sum+tree[rt*2+1].sum;
tree[rt].sum%=p;
}
void build(long rt,long long l,long r)
{
tree[rt].len=r-l+1;
tree[rt].mflag=1;
tree[rt].flag=0;
if(l==r)
{
tree[rt].sum=a[l];
tree[rt].sum%=p;
return ;
}
int mid=(l+r)/2;
build(rt*2,l,mid);
build(rt*2+1,mid+1,r);
pushup(rt);
return ;
}
void mul(long rt,long tl,long tr,long long l,long long r,long long c)
{
if(tl>=l&&r>=tr)
{
tree[rt].mflag*=c;
tree[rt].mflag%=p;
tree[rt].flag*=c;
tree[rt].flag%=p;
tree[rt].sum*=c;
tree[rt].sum%=p;
return ;
}
pushdown(rt);
int mid=(tr+tl)/2;
if(mid>=l)
mul(rt*2,tl,mid,l,r,c);
if(mid<r)
mul(rt*2+1,mid+1,tr,l,r,c);
pushup(rt);
return ;
}
void add(long rt,long tl,long tr,long long l,long long r,long long c)
{
if(tl>=l&&r>=tr)
{
tree[rt].flag+=c;
tree[rt].flag%=p;
tree[rt].sum+=c*tree[rt].len;
tree[rt].sum%=p;
return ;
}
pushdown(rt);
int mid=(tr+tl)/2;
if(mid>=l)
add(rt*2,tl,mid,l,r,c);
if(mid<r)
add(rt*2+1,mid+1,tr,l,r,c);
pushup(rt);
return ;
}
void query(long rt,long tl,long tr,long long l,long long r)
{
if(tl>=l&&r>=tr)
{
ans+=tree[rt].sum;
ans=ans%p;
return ;
}
pushdown(rt);
int mid=(tr+tl)/2;
if(mid>=l)
query(rt*2,tl,mid,l,r);
if(mid<r)
query(rt*2+1,mid+1,tr,l,r);
return ;
}
int main()
{
scanf("%d %d",&n,&p);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,1,n);
scanf("%d",&m);
while(m--)
{
int l,r,c;
int zl;
scanf("%d",&zl);
if(zl==1)
{
scanf("%d %d %d",&l,&r,&c);
mul(1,1,n,l,r,c);
}
else if(zl==2)
{
scanf("%d %d %d",&l,&r,&c);
add(1,1,n,l,r,c);
}
else
{
scanf("%d %d",&l,&r);
ans=0;
query(1,1,n,l,r);
printf("%lld\n",ans%p);
}
}
return 0;
}