【模板】线段树 2 - 洛谷
核心思路
注意到
所以,分别维护标记 add 和 mul 即可
AC 代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1000000+9;
#define md %=mod
#define tp t[p]
#define ls t[p*2]
#define rs t[p*2+1]
#define s t
int mod;
struct node{
int l,r,sum,mul,add;
};
node t[N*4];
int a[N];
void push_up(int p){
t[p].sum = t[p*2].sum+t[p*2+1].sum;
t[p].sum md;
}
void push_down(int pos){
s[pos << 1].sum = (s[pos << 1].sum * s[pos].mul + s[pos].add * (s[pos << 1].r - s[pos << 1].l + 1)) % mod;
s[pos << 1].mul = (s[pos << 1].mul * s[pos].mul) % mod;
s[pos << 1].add = (s[pos << 1].add * s[pos].mul + s[pos].add) % mod;
s[pos << 1|1].sum = (s[pos << 1|1].sum * s[pos].mul + s[pos].add * (s[pos << 1|1].r - s[pos << 1|1].l + 1)) % mod;
s[pos << 1|1].mul = (s[pos << 1|1].mul * s[pos].mul) % mod;
s[pos << 1|1].add = (s[pos << 1|1].add * s[pos].mul + s[pos].add) % mod;
s[pos].add = 0;
t[pos].mul = 1;
}
void build(int p,int l,int r){
t[p].l = l;
t[p].r = r;
t[p].mul = 1;
if(l == r){
t[p].sum = a[l];
return;
}
int mid = (l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
push_up(p);
}
void add(int p,int begin,int end,int l,int r,int x){
//cout<<l<<" "<<r<<" "<<begin<<" "<<end<<endl;
if(l == begin&&end == r){
t[p].add += x;
t[p].add md;
t[p].sum += (r-l+1)*x;
t[p].sum md;
return;
}
int mid = (begin+end)/2;
push_down(p);
//cout<<mid<<endl;
if(r <= mid){
//cout<<"L"<<endl;
add(p*2,begin,mid,l,r,x);
}
else if(l > mid){
//cout<<"R"<<endl;
add(p*2+1,mid+1,end,l,r,x);
}
else{
// cout<<"LR"<<endl;
add(p*2,begin,mid,l,mid,x);
add(p*2+1,mid+1,end,mid+1,r,x);
}
push_up(p);
}
void ChangeMul(int pos, int x, int y, int k) {
if (x <= s[pos].l && s[pos].r <= y) {
s[pos].add = (s[pos].add * k) % mod;
s[pos].mul = (s[pos].mul * k) % mod;
s[pos].sum = (s[pos].sum * k) % mod;
return;
}
push_down(pos);
int mid = (s[pos].l + s[pos].r) >> 1;
if (x <= mid) ChangeMul(pos << 1, x, y, k);
if (y > mid) ChangeMul(pos << 1 | 1, x, y, k);
push_up(pos);
return;
}
long long AskRange(int pos, int x, int y) {
if (x <= s[pos].l && s[pos].r <= y) {
return s[pos].sum;
}
push_down(pos);
long long val = 0;
int mid = (s[pos].l + s[pos].r) >> 1;
if (x <= mid) val = (val + AskRange(pos << 1, x, y)) % mod;
if (y > mid) val = (val + AskRange(pos << 1 | 1, x, y)) % mod;
return val;
}
int n,m;
signed main(){
cin>>n>>m>>mod;
for(int i = 1;i <= n;i++){
cin>>a[i];
}
build(1,1,n);
for(int i = 1;i <= m;i++){
int op;
cin>>op;
if(op == 1){
int x,y,k;
cin>>x>>y>>k;
ChangeMul(1,x,y,k);
}
else if(op == 2){
int x,y,k;
cin>>x>>y>>k;
add(1,1,n,x,y,k);
}
else{
int x,y;
cin>>x>>y;
cout<<AskRange(1,x,y)%mod<<endl;
}
}
return 0;
}