标签:ref type else main pre lld lse i++ turn
题目链接:https://www.luogu.org/problemnew/show/P2023
一道裸的线段树区间修改题,懒惰数组注意要先乘后加
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxx = 400010;
LL tree[maxx],lazy1[maxx],lazy2[maxx],a[maxx],mod;
int n;
void build(int l,int r,int temp)
{
lazy1[temp]=1;lazy2[temp]=0;
if(l==r)
{
tree[temp]=a[l]%mod;
return;
}
int mid=(l+r)/2;
build(l,mid,temp*2);
build(mid+1,r,temp*2+1);
tree[temp]=(tree[temp*2]+tree[temp*2+1])%mod;
}
void pushdown(int l,int r,int temp)
{
//lazy1[temp*2]=a0,lazy2[temp*2]=b0,lazy1[temp]=a
//a0*x+b0->a*(a0*x+b0)->a*a0*x+a*b0
tree[temp*2]=(tree[temp*2]*lazy1[temp]+l*lazy2[temp])%mod;
tree[temp*2+1]=(tree[temp*2+1]*lazy1[temp]+r*lazy2[temp])%mod;
lazy1[temp*2]=(lazy1[temp*2]*lazy1[temp])%mod;
lazy1[temp*2+1]=(lazy1[temp*2+1]*lazy1[temp])%mod;
lazy2[temp*2]=(lazy2[temp*2]*lazy1[temp]+lazy2[temp])%mod;
lazy2[temp*2+1]=(lazy2[temp*2+1]*lazy1[temp]+lazy2[temp])%mod;
lazy1[temp]=1;lazy2[temp]=0;
}
void add1(int l,int r,int p,int q,LL c,int temp)
{
if(p<=l&&r<=q)
{
tree[temp]=(tree[temp]*c)%mod;
lazy1[temp]=(lazy1[temp]*c)%mod;
lazy2[temp]=(lazy2[temp]*c)%mod;//注意这里,乘的发生改变加的就要改变
return;
}
int mid=(l+r)/2;
pushdown(mid-l+1,r-mid,temp);
if(mid>=p)add1(l,mid,p,q,c,temp*2);
if(mid<q)add1(mid+1,r,p,q,c,temp*2+1);
tree[temp]=(tree[temp*2]+tree[temp*2+1])%mod;
}
void add2(int l,int r,int p,int q,LL c,int temp)
{
if(p<=l&&r<=q)
{
tree[temp]=(tree[temp]+(r-l+1)*c)%mod;
lazy2[temp]=(lazy2[temp]+c)%mod;
return;
}
int mid=(l+r)/2;
pushdown(mid-l+1,r-mid,temp);
if(mid>=p)add2(l,mid,p,q,c,temp*2);
if(mid<q)add2(mid+1,r,p,q,c,temp*2+1);
tree[temp]=(tree[temp*2]+tree[temp*2+1])%mod;
}
LL get(int l,int r,int p,int q,int temp)
{
if(p<=l&&r<=q)return tree[temp];
int mid=(l+r)/2;
LL res=0;
pushdown(mid-l+1,r-mid,temp);
if(mid>=p)res=(res+get(l,mid,p,q,temp*2))%mod;
if(mid<q)res=(res+get(mid+1,r,p,q,temp*2+1))%mod;
return res;
}
int main()
{
scanf("%d %lld",&n,&mod);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,n,1);
int m,s,t,g;
LL c;
scanf("%d",&m);
while(m--)
{
scanf("%d",&s);
if(s==1)
{
scanf("%d%d%lld",&t,&g,&c);
add1(1,n,t,g,c,1);
}
else if(s==2)
{
scanf("%d%d%lld",&t,&g,&c);
add2(1,n,t,g,c,1);
}
else
{
scanf("%d%d",&t,&g);
LL ans=get(1,n,t,g,1);
printf("%lld\n",ans);
}
}
return 0;
}
P2023 [AHOI2009]维护序列 (线段树区间修改查询)
标签:ref type else main pre lld lse i++ turn
原文地址:https://www.cnblogs.com/HooYing/p/11247399.html