• 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
    ",query(1,n,x,y,1));
            }
        }
    }
  • 相关阅读:
    一个回车键黑掉一台服务器——使用Docker时不要这么懒啊喂
    docker machine介绍和使用
    Docker Engine和Docker Machine介绍
    Nginx服务器之负载均衡策略
    从linux启动到rootfs的挂载分析
    Docker容器的生命周期管理
    docker的使用
    automake,autoconf使用详解
    go语言中文网中的资源
    Go工具和调试详解
  • 原文地址:https://www.cnblogs.com/jiangminghong/p/9816162.html
Copyright © 2020-2023  润新知