线段树模板二
题目描述
如题,已知一个数列,你需要进行下面三种操作:
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
#include<bits/stdc++.h> typedef long long ll; using namespace std; const int maxn=2e5+9; struct tree{ int l,r; ll sum,add,mul; }a[maxn<<2]; ll s[maxn],p; void update(int k) { a[k].sum=(a[k<<1].sum+a[k<<1|1].sum)%p; } void build(int k,int l,int r) { a[k].l=l,a[k].r=r; a[k].add=0; a[k].mul=1; if(l==r) { a[k].sum=s[l];return; } int mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); update(k); } void pushdown(int k) { if(a[k].l==a[k].r) { a[k].add=0; a[k].mul=1; return; } int mid=(a[k].l+a[k].r)>>1; a[k<<1].sum=(a[k<<1].sum*a[k].mul+a[k].add*(mid-a[k].l+1))%p; a[k<<1|1].sum=(a[k<<1|1].sum*a[k].mul+a[k].add*(a[k].r-mid))%p; a[k<<1].add=(a[k<<1].add*a[k].mul+a[k].add)%p; a[k<<1|1].add=(a[k<<1|1].add*a[k].mul+a[k].add)%p; a[k<<1].mul=(a[k<<1].mul*a[k].mul)%p; a[k<<1|1].mul=(a[k<<1|1].mul*a[k].mul)%p; a[k].add=0; a[k].mul=1; return; } void changeplus(int k,int l,int r,int x) { // cout<<a[k].sum<<"??"<<endl; if(a[k].l>r||a[k].r<l)return; if(l<=a[k].l&&r>=a[k].r) { a[k].sum=(a[k].sum+x*(a[k].r-a[k].l+1))%p; a[k].add=(a[k].add+x)%p; return; } pushdown(k); int mid=(a[k].l+a[k].r)>>1; // if(l<=mid) changeplus(k<<1,l,r,x); // if(r>mid) changeplus(k<<1|1,l,r,x); update(k); return; } void changemul(int k,int l,int r,int x) { // cout<<a[k].sum<<"!!"<<endl; if(a[k].l>r||a[k].r<l)return; if(l<=a[k].l&&r>=a[k].r) { a[k].sum=(a[k].sum*x)%p; a[k].mul=(a[k].mul*x)%p; a[k].add=(a[k].add*x)%p; return; } pushdown(k); int mid=(a[k].l+a[k].r)>>1; // if(l<=mid) changemul(k<<1,l,r,x); // if(r>mid) changemul(k<<1|1,l,r,x); update(k); return; } ll query(int k,int l,int r) { if(r<a[k].l||l>a[k].r)return 0; pushdown(k); if(l<=a[k].l&&r>=a[k].r) { return a[k].sum; } int mid=(a[k].l+a[k].r)>>1; ll ans=0; // if(l<=mid) ans=(ans+query(k<<1,l,r))%p; // if(r>mid) ans=(ans+query(k<<1|1,l,r))%p; return ans; } int main() { int n,m,i; scanf("%d%d%lld",&n,&m,&p); for(i=1;i<=n;i++) scanf("%lld",&s[i]); build(1,1,n); while(m--) { int opt,L,R; ll x; scanf("%d",&opt); if(opt==1) { scanf("%d%d%lld",&L,&R,&x); changemul(1,L,R,x); } if(opt==2) { scanf("%d%d%lld",&L,&R,&x); changeplus(1,L,R,x); } if(opt==3) { scanf("%d%d",&L,&R); printf("%lld\n",query(1,L,R)); } } }
欢迎加我qq1165750856一起玩呀~