传送门
题意就是给你一系列数字,有3中操作
- 给你一个区间,将这个区间里面的所有数字全部乘以一个给定值c
- 给你一个区间,将这个区间里面的所有数字全部加上一个给定值c
- 给你一个区间,询问这个区间的和
这道题要用线段树维护一个加,一个乘
lazy0维护的是加
lazy1维护的是乘
任何的一个x对它进行乘和加的操作最终结果总可以写成形如ax+b的形式,
在这里的a就是我们需要维护的乘了, 显然b就是我们要维护的加
举个栗子:
(x*4+3)*2+3=8*x+9
lazy1=4*2
lazy0=3*2+3
#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<vector>
#include<queue>
#include<string>
#include <cmath>
#define mod 999997
#define lson l, mid, root << 1
#define rson mid + 1, r, root << 1 | 1
#define father l , r , root
#define lowbit(x) ( x & ( - x ) )
using namespace std;
typedef long long ll;
const int maxn = 100100;
const int inf = 0x3f3f3f3f;
ll n,p;
ll num[maxn];
ll sum[maxn<<2];//区间和
ll lazy1[maxn<<2];//维护乘
ll lazy0[maxn<<2];//维护加
void push_up(ll root){
sum[root]=(sum[root<<1]+sum[root<<1|1])%p;
return ;
}
void push_down(ll l,ll r,ll root){
if(lazy0[root]==0&&lazy1[root]==1) return ;
ll ql=root<<1;
ll qr=root<<1|1;
ll mid=(l+r)>>1;
sum[ql]=(sum[ql]*lazy1[root]+lazy0[root]*(mid-l+1))%p;
sum[qr]=(sum[qr]*lazy1[root]+lazy0[root]*(r-mid))%p;
//更新左区间的信息
lazy1[ql]=lazy1[ql]*lazy1[root]%p;
lazy0[ql]=(lazy0[root]+lazy1[root]*lazy0[ql])%p;
//更新右区间的信息
lazy1[qr]=lazy1[qr]*lazy1[root]%p;
lazy0[qr]=(lazy0[qr]*lazy1[root]+lazy0[root])%p;
//更新过后取消标记
lazy0[root]=0;
lazy1[root]=1;
}
void build_tree(ll l,ll r,ll root){
lazy0[root]=0;
lazy1[root]=1;
if(l==r){
sum[root]=num[l]%p;
return;
}
ll mid=(l+r)>>1;
build_tree(lson);
build_tree(rson);
push_up(root);
}
void change(ll L,ll R,ll c,ll temp,ll l,ll r,ll root){
if(L<=l&&R>=r){
if(temp==1){
sum[root]=(sum[root]*c)%p;
lazy1[root]=(lazy1[root]*c)%p;
lazy0[root]=(lazy0[root]*c)%p;//注意,这里应该是乘
}else{
sum[root]=(sum[root]+c*(r-l+1))%p;
lazy0[root]=(lazy0[root]+c)%p;
}
return ;
}
push_down(l,r,root);
ll mid=(l+r)>>1;
if(mid>=L)change(L,R,c,temp,lson);
if(mid<R)change(L,R,c,temp,rson);
push_up(root);
}
ll query(ll L,ll R,ll l,ll r ,ll root){
if(L<=l&&R>=r){
return sum[root];
}
push_down(l,r,root);
ll ans=0;
ll mid=(l+r)>>1;
if(mid>=L)ans=(ans+query(L,R,lson))%p;
if(mid<R)ans=(ans+query(L,R,rson))%p;
return ans%p;
}
int main(){
while(~scanf("%lld%lld",&n,&p)){
//scanf("%lld%lld",&n,&p);
for(ll i=1;i<=n;i++){
scanf("%lld",&num[i]);
}
build_tree(1,n,1);
ll q;
scanf("%lld",&q);
while(q--){
ll flag,t,g,c;
scanf("%lld",&flag);
if(flag==3){
scanf("%lld%lld",&t,&g);
printf("%lld\n",query(t,g,1,n,1));
}else{
scanf("%lld%lld%lld",&t,&g,&c);
change(t,g,c,flag,1,n,1);
}
}
}
return 0;
}