【模板】线段树 2

it2022-05-05  238

题目描述 如题,已知一个数列,你需要进行下面三种操作:

1.将某区间每一个数乘上x

2.将某区间每一个数加上x

3.求出某区间每一个数的和

输入格式 第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。

第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

接下来M行每行包含3或4个整数,表示一个操作,具体如下:

操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k

操作2: 格式:2 x y k 含义:将区间[x,y]内每个数加上k

操作3: 格式:3 x y 含义:输出区间[x,y]内每个数的和对P取模所得的结果

输出格式 输出包含若干行整数,即为所有操作3的结果。

输入输出样例 输入 #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 说明/提示 时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=8,M<=10

对于70%的数据:N<=1000,M<=10000

对于100%的数据:N<=100000,M<=100000

(数据已经过加强_

样例说明:

故输出应为17、2(40 mod 38=2)`#include #include using namespace std;

int p;

long long a[100007];

struct node{ long long v,mul,add; }st[400007];

void bt(int root,int l,int r){ st[root].mul=1; st[root].add=0; if(l==r){ st[root].v=a[l]; } else{ int m=(l+r)/2; bt(root2,l,m); bt(root2+1,m+1,r); st[root].v=st[root2].v+st[root2+1].v; } st[root].v%=p; return; }

void pushdown(int root,int l,int r){ int m=(l+r)/2; st[root2].v=(st[root2].vst[root].mul+st[root].add(m-l+1))%p; st[root2+1].v=(st[root2+1].vst[root].mul+st[root].add(r-m))%p; st[root2].mul=(st[root2].mulst[root].mul)%p; st[root2+1].mul=(st[root2+1].mulst[root].mul)%p; st[root2].add=(st[root2].addst[root].mul+st[root].add)%p; st[root2+1].add=(st[root2+1].addst[root].mul+st[root].add)%p; st[root].mul=1; st[root].add=0; return; }

void ud1(int root, int stdl, int stdr, int l, int r, long long k){ if(r<stdl||stdr<l){ return ; } if(l<=stdl && stdr<=r){ st[root].v=(st[root].vk)%p; st[root].mul=(st[root].mulk)%p; st[root].add=(st[root].addk)%p; return ; } pushdown(root, stdl, stdr); int m=(stdl+stdr)/2; ud1(root2, stdl, m, l, r, k); ud1(root2+1, m+1, stdr, l, r, k); st[root].v=(st[root2].v+st[root2+1].v)%p; return; } void ud2(int root, int stdl, int stdr, int l, int r, long long k){ if(r<stdl||stdr<l){ return; } if(l<=stdl && stdr<=r){ st[root].add=(st[root].add+k)%p; st[root].v=(st[root].v+k(stdr-stdl+1))%p; return; } pushdown(root, stdl, stdr); int m=(stdl+stdr)/2; ud2(root2, stdl, m, l, r, k); ud2(root2+1, m+1, stdr, l, r, k); st[root].v=(st[root2].v+st[root2+1].v)%p; return; }

long long query(int root,int stdl,int stdr,int l,int r){ if(r<stdl||stdr<l){ return 0; } if(l<=stdl && stdr<=r){ return st[root].v; } pushdown(root,stdl,stdr); int m=(stdl+stdr)/2; return (query(root2, stdl, m, l, r)+query(root2+1, m+1, stdr, l, r))%p; }

int main(){ int n, m; scanf("%d%d%d", &n, &m, &p); for(int i=1; i<=n; i++){ scanf("%lld", &a[i]); } bt(1, 1, n); while(m–){ int chk; scanf("%d", &chk); int x, y; long long k; if(chk1){ scanf("%d%d%lld", &x, &y, &k); ud1(1, 1, n, x, y, k); } else if(chk2){ scanf("%d%d%lld", &x, &y, &k); ud2(1, 1, n, x, y, k); } else{ scanf("%d%d", &x, &y); printf("%lld\n", query(1, 1, n, x, y)); } } return 0; }`


最新回复(0)