题目描述
如题,已知一个数列,你需要进行下面三种操作:
-
将某区间每一个数乘上 xx
-
将某区间每一个数加上 xx
-
求出某区间每一个数的和
输入格式
第一行包含三个整数 n,m,pn,m,p,分别表示该数列数字的个数、操作的总个数和模数。
第二行包含 nn 个用空格分隔的整数,其中第 ii 个数字表示数列第 ii 项的初始值。
接下来 mm 行每行包含若干个整数,表示一个操作,具体如下:
操作 11: 格式:1 x y k
含义:将区间 [x,y][x,y] 内每个数乘上 kk
操作 22: 格式:2 x y k
含义:将区间 [x,y][x,y] 内每个数加上 kk
操作 33: 格式:3 x y
含义:输出区间 [x,y][x,y] 内每个数的和对 pp 取模所得的结果
输出格式
输出包含若干行整数,即为所有操作 33 的结果。
输入输出样例
输入 #1复制
5 5 38 1 5 4 2 3 2 1 4 1 3 2 5 1 2 4 2 2 3 5 5 3 1 4
输出 #1复制
17 2
说明/提示
【数据范围】
对于 30\%30% 的数据:n \le 8n≤8,m \le 10m≤10
对于 70\%70% 的数据:n \le 10^3n≤103,m \le 10^4m≤104
对于 100\%100% 的数据:n \le 10^5n≤105,m \le 10^5m≤105
除样例外,p = 571373p=571373
(数据已经过加强^_^)
样例说明:
故输出应为 17
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 100010;
int p,in[MAXN];
struct Segment_Tree{
struct info{
int l,r,plz,mlz = 1;
ll sum;
}node[MAXN << 2];
void Build(int n,int l,int r){
node[n].l = l,node[n].r = r;
if(l == r){
node[n].sum = in[l];
return;
}
int mid = (l+r) >> 1;
Build(n << 1,l,mid);
Build(n << 1|1,mid+1,r);
node[n].sum = (node[n << 1].sum + node[n << 1|1].sum) % p;
return;
}
inline void push_down(int i){
ll k1 = node[i].plz,k2 = node[i].mlz;
int lt = i << 1,rt = i << 1|1;
node[lt].sum = (node[lt].sum*k2 + k1*(node[lt].r - node[lt].l + 1) % p) % p;
node[rt].sum = (node[rt].sum*k2 + k1*(node[rt].r - node[rt].l + 1) % p) % p;
node[lt].mlz = (node[lt].mlz*k2) % p;
node[rt].mlz = (node[rt].mlz*k2) % p;
node[lt].plz = (node[lt].plz*k2+k1) % p;
node[rt].plz = (node[rt].plz*k2+k1) % p;
node[i].plz = 0;
node[i].mlz = 1;
return;
}
void plu(int i,int l,int r,ll k){
if(node[i].l >= l && node[i].r <= r){
node[i].sum = (node[i].sum + k*(node[i].r - node[i].l + 1) % p) % p;
node[i].plz = (node[i].plz + k) % p;
return;
}
push_down(i);
int lt = i << 1,rt = i << 1|1;
if(node[lt].r >= l) plu(lt,l,r,k);
if(node[rt].l <= r) plu(rt,l,r,k);
node[i].sum = (node[lt].sum + node[rt].sum) % p;
return;
}
void mul(int i,int l,int r,ll k){
if(node[i].l >= l && node[i].r <= r){
node[i].sum = (node[i].sum * k) % p;
node[i].mlz = (node[i].mlz * k) % p;
node[i].plz = (node[i].plz * k) % p;
return;
}
push_down(i);
int lt = i << 1,rt = i << 1|1;
if(node[lt].r >= l) mul(lt,l,r,k);
if(node[rt].l <= r) mul(rt,l,r,k);
node[i].sum = (node[lt].sum + node[rt].sum) % p;
}
inline ll query(int i,int l,int r){
if(node[i].l >= l && node[i].r <= r) return node[i].sum;
if(node[i].r < l && node[i].l > r) return 0;
push_down(i);
ll s = 0;
int lt = i << 1,rt = i << 1|1;
if(node[lt].r >= l) s = (s + query(lt,l,r)) % p;
if(node[rt].l <= r) s = (s + query(rt,l,r)) % p;
return s % p;
}
}ST;
int main()
{
int n,m,t,x,y,k;
scanf("%d %d %d",&n,&m,&p);
for(int i = 1;i <= n; i++)
scanf("%d",&in[i]);
ST.Build(1,1,n);
while(m--){
scanf("%d",&t);
if(t == 1){
scanf("%d %d %d",&x,&y,&k);
ST.mul(1,x,y,k);
}
if(t == 2){
scanf("%d %d %d",&x,&y,&k);
ST.plu(1,x,y,k);
}
if(t == 3){
scanf("%d %d",&x,&y);
ll res = ST.query(1,x,y);
printf("%lld\n",res);
}
}
return 0;
}