BZOJ1798 [Ahoi2009]Seq 维护序列

题目描述:

老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。

有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式:

(1)把数列中的一段数全部乘一个值;

(2)把数列中的一段数全部加一个值;

(3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。

 

题解:

线段树的基本操作。

但是注意lazy标记下传时乘与加的先后顺序。

我这里是先乘后加。

附上代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=400100;
int n,m,a[N>>2];
long long p,tag[N],tag2[N],sum[N];
void pushup(int k) 
{
    sum[k]=(sum[k<<1]+sum[k<<1|1])%p;
}
void build(int l,int r,int k)
{
    tag2[k]=1;
    if(l==r)
    {
        sum[k]=a[l]%p;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,k<<1);
    build(mid+1,r,k<<1|1);
    pushup(k);
}
void lazy(int l,int r,int k,int len)
{
    (tag[k]+=len)%=p;
    sum[k]=(sum[k]+1ll*(r-l+1)*len)%p;
}
void lazy2(int l,int r,int k,int len)
{
    (tag[k]*=len)%=p;
    (tag2[k]*=len)%=p;
    sum[k]=(sum[k]*len)%p;
}
void pushdown(int l,int r,int k)
{
    int mid=(l+r)>>1;
    if(tag2[k]!=1)
    {
        lazy2(l,mid,k<<1,tag2[k]);
        lazy2(mid+1,r,k<<1|1,tag2[k]);
        tag2[k]=1;
    }
    if(tag[k]!=0)
    {
        lazy(l,mid,k<<1,tag[k]);
        lazy(mid+1,r,k<<1|1,tag[k]);
        tag[k]=0; 
    }
}
void update1(int l,int r,int x,int y,int k,int len)
{
    if(x<=l&&r<=y)
    {
        sum[k]=(sum[k]*len)%p;
        (tag[k]*=len)%=p;
        (tag2[k]*=len)%=p;
        return;
    }
    pushdown(l,r,k);
    int mid=(l+r)>>1;
    if(mid>=x)
        update1(l,mid,x,y,k<<1,len);
    if(mid<y)
        update1(mid+1,r,x,y,k<<1|1,len);
    pushup(k);
}
void update2(int l,int r,int x,int y,int k,int len)
{
    if(x<=l&&r<=y)
    {
        sum[k]=(sum[k]+(r-l+1)*len)%p;
        (tag[k]+=len)%=p;
        return;
    }
    pushdown(l,r,k);
    int mid=(l+r)>>1;
    if(mid>=x)
        update2(l,mid,x,y,k<<1,len);
    if(mid<y)
        update2(mid+1,r,x,y,k<<1|1,len);
    pushup(k);
}
long long query(int l,int r,int x,int y,int k)
{
    if(x<=l&&r<=y)
        return sum[k];
    pushdown(l,r,k);
    int mid=(l+r)>>1;
    long long ans=0;
    if(mid>=x)
        ans=(ans+query(l,mid,x,y,k<<1))%p;
    if(mid<y)
        ans=(ans+query(mid+1,r,x,y,k<<1|1))%p;
    return ans;
}
int main()
{
    scanf("%d%lld",&n,&p);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    build(1,n,1);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        int k,x,y,s;
        scanf("%d",&s);
        if(s==1)
        {
            scanf("%d%d%d",&x,&y,&k);
            update1(1,n,x,y,1,k);
        }
        if(s==2)
        {
            scanf("%d%d%d",&x,&y,&k);
            update2(1,n,x,y,1,k);
        }
        if(s==3)
        {
            scanf("%d%d",&x,&y);
            printf("%lld\n",query(1,n,x,y,1));
        }
    }
}

 

posted @ 2018-10-19 14:15  jiangminghong  阅读(148)  评论(0编辑  收藏  举报