https://www.luogu.org/problemnew/show/P2023
题解
乘法的标记和加法的标记相同,主要差别是在标记下传的时候,一定要先对之前的标记进行操作,即把当前的数乘以乘法标记再加上加法标记,这步必须同时进行,因为如果分开的话,若是加上加法标记再做乘法的话答案就会出错。
代码
#include <bits/stdc++.h>
using namespace std;
#define FOR0(a,b) for(int i = a; i < b; ++i)
#define FORE(a,b) for(int i = a; i <= b; ++i)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 200000+10;
ll sum[maxn<<2],N,P,lazy[maxn<<2],lazy2[maxn<<2],M;
void pushup(int rt) {
sum[rt] = (sum[rt<<1]+sum[rt<<1|1])%P;
}
void pushdown(int rt, int l,int r) {
int mid = (l+r)>>1;
sum[rt<<1] = (1ll*sum[rt<<1]*lazy2[rt]+1ll*(mid-l+1)*lazy[rt]%P)%P;
sum[rt<<1|1] = (1ll*sum[rt<<1|1]*lazy2[rt]+1ll*(r-mid)*lazy[rt]%P)%P;
// if(lazy[rt]) {
lazy[rt<<1] = (1ll*lazy[rt<<1]*lazy2[rt]%P+lazy[rt])%P;
lazy[rt<<1|1] = (1ll*lazy[rt<<1|1]*lazy2[rt]%P+lazy[rt])%P;
lazy[rt] = 0;
// }
// if(lazy2[rt] != 1) {
lazy2[rt<<1] = (1ll*lazy2[rt<<1]*lazy2[rt])%P;
lazy2[rt<<1|1] = (1ll*lazy2[rt<<1|1]*lazy2[rt])%P;
lazy2[rt] = 1;
// }
}
void build(int l,int r,int rt) {
lazy[rt] = 0; lazy2[rt] = 1;
if(l == r) {
scanf("%d", &sum[rt]);
return;
}
int mid = (l+r)>>1;
build(lson); build(rson);
pushup(rt);
}
void updateAdd(int L, int R, int v,int l,int r,int rt) {
if(L > r || R < l)
return;
if(L <= l && r <= R) {
sum[rt] = (sum[rt]+(r-l+1)*v%P)%P;
lazy[rt] = (lazy[rt]+v)%P;
return;
}
int mid = (l+r)>>1;
pushdown(rt,l,r);
updateAdd(L,R,v,lson);
updateAdd(L,R,v,rson);
pushup(rt);
}
void updateMul(int L, int R, int v,int l,int r,int rt) {
if(L > r || R < l)
return;
if(L <= l && r <= R) {
sum[rt] = (1ll*sum[rt]*v)%P;
lazy2[rt] = (1ll*lazy2[rt]*v)%P;
lazy[rt] = (1ll*lazy[rt]*v)%P;
return;
}
int mid = (l+r)>>1;
pushdown(rt,l,r);
updateMul(L,R,v,lson);
updateMul(L,R,v,rson);
pushup(rt);
}
ll query(int L, int R,int l,int r,int rt) {
if(L > r || R < l)
return 0;
if(L <= l && r <= R) {
return sum[rt];
}
int mid = (l+r)>>1;
pushdown(rt,l,r);
ll v = (query(L,R,lson)+query(L,R,rson))%P;
pushup(rt);
return v;
}
int main() {
scanf("%d%d", &N, &P);
build(1,N,1);
scanf("%d", &M);
int opt, t,g,c;
for(int i = 0; i < M; ++i) {
scanf("%d", &opt);
if(opt == 1) {
scanf("%d%d%d", &t, &g, &c);
updateMul(t,g,c,1,N,1);
// cout << query(3,3,1,N,1) << endl;
} else if(opt == 2) {
scanf("%d%d%d", &t, &g, &c);
updateAdd(t,g,c,1,N,1);
} else if(opt == 3) {
scanf("%d%d", &t, &g);
cout << query(t,g,1,N,1) << endl;
}
}
return 0;
}