[AHOI2009]维护序列

Posted 宣毅鸣

tags:

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

题解:

看到这种题目,一看就是线段树

很明显的区间线段树

加法反正不用说

乘法的时候往加法的地方也要翻倍

代码:

#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
const int N=400005;
ll p,v,sum_,addv[N],mulv[N],sumv[N],a[N];
int n,m,c,x,y;
void pushdown(int o,int l,int l1,int r,int r1)
{
    sumv[o*2]=(sumv[o*2]*mulv[o]+addv[o]*(l1-l+1))%p;
    sumv[o*2+1]=(sumv[o*2+1]*mulv[o]+addv[o]*(r1-r+1))%p;
    addv[o*2]=(addv[o*2]*mulv[o]+addv[o])%p;
    addv[o*2+1]=(addv[o*2+1]*mulv[o]+addv[o])%p;
    mulv[o*2]=(mulv[o*2]*mulv[o])%p;
    mulv[o*2+1]=(mulv[o*2+1]*mulv[o])%p;
    mulv[o]=1;
    addv[o]=0;
}
void updatemul(int o,int l,int r)
{    
    if(x<=l&&r<=y)
     {
        mulv[o]=(mulv[o]*v)%p;
        addv[o]=(addv[o]*v)%p;
        sumv[o]=(sumv[o]*v)%p;
        return ;
     }
    int mid=(l+r)>>1;
    pushdown(o,l,mid,mid+1,r);
    if(x<=mid)updatemul(o*2,l,mid);
    if(y>mid)updatemul(o*2+1,mid+1,r);
    sumv[o]=(sumv[o*2]+sumv[o*2+1])%p;
}
void updateadd(int o,int l,int r)
{
    if(x<=l&&r<=y)
     {
        addv[o]=(addv[o]+v)%p;
        sumv[o]=(sumv[o]+v*(r-l+1))%p;
        return ;
     }
    int mid=(l+r)>>1;
    pushdown(o,l,mid,mid+1,r);
    if(x<=mid)updateadd(o*2,l,mid);
    if(y>mid)updateadd(o*2+1,mid+1,r);
    sumv[o]=(sumv[o*2]+sumv[o*2+1])%p;
}
void create(int o,int l,int r)
{
    addv[o]=0;
    mulv[o]=1;
    if(l==r)
     {
        sumv[o]=a[l];
        return ;
     }
    int mid=(l+r)>>1;
    create(o*2,l,mid);
    create(o*2+1,mid+1,r);
    sumv[o]=(sumv[o*2]+sumv[o*2+1])%p;
}
void query(int o,int l,int r)
{
    if(x<=l&&r<=y)
     {
        sum_+=sumv[o]%p;
        sum_%=p;
        return ;
     }
    int mid=(l+r)>>1;
    pushdown(o,l,mid,mid+1,r);
    if(x<=mid)query(o*2,l,mid);
    if(y>mid)query(o*2+1,mid+1,r);
    sumv[o]=(sumv[o*2]+sumv[o*2+1])%p;
}
int main()
{
    scanf("%d%d",&n,&p);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    create(1,1,n);
    scanf("%d",&m);
    while (m--)
     {
        scanf("%d%d%d",&c,&x,&y);
        if(c==1)
         {
            scanf("%d",&v);
            updatemul(1,1,n);
         }
        if(c==2)
         {
            scanf("%d",&v);
            updateadd(1,1,n);
         }
        if(c==3)
         {
            sum_=0;
            query(1,1,n);
            printf("%lld\n",sum_);
         }
     }
    return 0;
}

 

以上是关于[AHOI2009]维护序列的主要内容,如果未能解决你的问题,请参考以下文章

[AHOI2009]维护序列

BZOJ 1798 AHOI2009 Seq 维护序列 线段树

[AHOI2009]维护序列

[Luogu 2023] AHOI2009 维护序列

1798: [Ahoi2009]Seq 维护序列seq

bzoj1798: [Ahoi2009]Seq 维护序列seq 2011-12-20