P2023 [AHOI2009]维护序列 (线段树区间修改查询)

Posted hooying

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2023 [AHOI2009]维护序列 (线段树区间修改查询)相关的知识,希望对你有一定的参考价值。

题目链接: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]维护序列 (线段树区间修改查询)的主要内容,如果未能解决你的问题,请参考以下文章

P2023 [AHOI2009]维护序列 (线段树区间修改查询)

[P2023][AHOI2009]维护序列(线段树)

P2023 [AHOI2009] 维护序列(线段树水题)

P2023 [AHOI2009]维护序列 - 线段树区间乘法加法

P3373 线段树乘法模板 P2023 [AHOI2009]维护序列

[AHOI2009]维护序列