[luoguP3373]线段树2
1.我们规定先乘后加然后pushdown乘法的时候把加法一起乘就做出来了
坑:
1.pushup的时候忘了pushdown左右儿子,特别是add、mul操作中。 *不能以为把add操作中的当前点都pushdown一遍就没有问题, 有可能第一次操作在x<<1|1节点打标记然后下次操作你在x节点打标记,这样就会出问题 2.注意在判断出ql<=l&&qr>=r的时候return 3.注意ql,qr大部分时候是不用随着l,r改变的,我们直接判断当前段是否属于[ql,qr]即可 4.注意线段树要开到4N而不是2N,严格地说应该是开到2^(n+1),(2^n>=N), 同时,如果是开到4N,下放标记的时候要判一下l,r,否则可能RE
- 代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+6;
typedef long long ll;
int n,m;
ll mod,a[N];
struct segtree{
ll t[N*4],pl[N*4],cr[N*4];
inline void build(int x,int l,int r){
int mid=(l+r)>>1,lch=x<<1,rch=x<<1|1;
cr[x]=1;
if(l==r){t[x]=a[mid];return;}
build(lch,l,mid);
build(rch,mid+1,r);
t[x]=(t[lch]+t[rch])%mod;
}
inline void pushdown(int x,int l,int r){
ll len=r-l+1;
int lch=x<<1,rch=x<<1|1;
if(cr[x]!=1){
t[x]=t[x]*cr[x]%mod;
if(l<r)cr[lch]=(cr[lch]*cr[x])%mod,pl[lch]=(pl[lch]*cr[x])%mod,pl[rch]=(pl[rch]*cr[x])%mod,cr[rch]=(cr[rch]*cr[x])%mod;
cr[x]=1;
}
if(pl[x]){
t[x]=(t[x]+len*pl[x])%mod;
if(l<r)pl[lch]=(pl[lch]+pl[x])%mod,pl[rch]=(pl[rch]+pl[x])%mod;
pl[x]=0;
}
}
inline void add(int x,int l,int r,int ql,int qr,ll sum){
int mid=(l+r)>>1,lch=x<<1,rch=x<<1|1;
if(ql<=l&&qr>=r){
pushdown(x,l,r);
pl[x]=(pl[x]+sum)%mod;return;
}
pushdown(x,l,r);
if(qr>mid) add(rch,mid+1,r,ql,qr,sum);
if(ql<=mid) add(lch,l,mid,ql,qr,sum);
pushdown(lch,l,mid);
pushdown(rch,mid+1,r);
t[x]=(t[lch]+t[rch])%mod;
}
inline void mul(int x,int l,int r,int ql,int qr,ll sum){
int mid=(l+r)>>1,lch=x<<1,rch=x<<1|1;
if(ql<=l&&qr>=r){
pushdown(x,l,r);
cr[x]=cr[x]*sum%mod;return;
}
pushdown(x,l,r);
if(qr>mid) mul(rch,mid+1,r,ql,qr,sum);
if(ql<=mid) mul(lch,l,mid,ql,qr,sum);
pushdown(lch,l,mid);
pushdown(rch,mid+1,r);
t[x]=(t[lch]+t[rch])%mod;
}
inline ll qry(int x,int l,int r,int ql,int qr){
int mid=(l+r)>>1,lch=x<<1,rch=x<<1|1;
pushdown(x,l,r);
if(ql<=l&&qr>=r){
return t[x];
}
if(ql>mid)return qry(rch,mid+1,r,ql,qr);
if(qr<=mid)return qry(lch,l,mid,ql,qr);
return (qry(lch,l,mid,ql,qr)+qry(rch,mid+1,r,ql,qr))%mod;
}
}T;
int main()
{
scanf("%d%d%lld",&n,&m,&mod);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
T.build(1,1,n);
while(m--){
int opt,x,y;ll k;
scanf("%d%d%d",&opt,&x,&y);
if(opt==1){
scanf("%lld",&k);
T.mul(1,1,n,x,y,k);
}if(opt==2){
scanf("%lld",&k);
T.add(1,1,n,x,y,k);
}if(opt==3){
ll res=T.qry(1,1,n,x,y);
printf("%lld\n",res);
}
}
}