zoukankan      html  css  js  c++  java
  • 线段树相关

    模板链接:

    支持区间加减,乘。询问区间和。

    要注意的几点:

    1.输出格式!!!!

    2.$printf("")$语法要写对,不然的话能过编辑,半天调不出来。

    3.位运算的时候$>>1$和$<<1$和$<<1|1$分清……

    4.将什么$val[p]+=……,val[p]%=mod$ 要写到一句的时候,一定要记得$val[p]=val[p]+……$,不是$val[p]=……$

    好了,这$4$点调了一上午$……$

    代码奉上

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int mod;
    struct linetree{
        long long val[400010];
        long long lazyp[400010];
        long long lazym[400010];
        inline void update(int p,int l,int r)
        {
            val[p]=(val[p]*lazym[p])%mod,
            val[p]=(val[p]+(r-l)*lazyp[p])%mod;
            return ;
        }
        inline void pushdown(int p,int l,int r)
        {
            update(p,l,r);
            if(r-l>1)
            {
                lazyp[p<<1]=(lazyp[p<<1]*lazym[p]+lazyp[p])%mod,
                lazym[p<<1]=(lazym[p<<1]*lazym[p])%mod;
                lazyp[p<<1|1]=(lazyp[p<<1|1]*lazym[p]+lazyp[p])%mod,
                lazym[p<<1|1]=(lazym[p<<1|1]*lazym[p])%mod;            
            }lazyp[p]=0,lazym[p]=1;
    
            return ;
        }
        inline int build(int p,int l,int r)
        {
            lazym[p]=1;
            if(r-l==1) {scanf("%lld",&val[p]),val[p]%=mod;return val[p];}
            int mid=l+r>>1;
            if(mid>l) val[p]=(val[p]+build(p<<1,l,mid))%mod;
            if(mid<r) val[p]=(val[p]+build(p<<1|1,mid,r))%mod;
            return val[p];
        }
        void setpluse(int p,int l,int r,int dl,int dr,long long pluse)
        {
            if(lazyp[p]!=0||lazym[p]!=1) pushdown(p,l,r);
            if(l==dl&&r==dr){lazyp[p]=(lazyp[p]+pluse)%mod,pushdown(p,l,r);return ;}
            int mid=l+r>>1;
            if(mid>dl) setpluse(p<<1,l,mid,dl,min(mid,dr),pluse);else pushdown(p<<1,l,mid);
            if(mid<dr) setpluse(p<<1|1,mid,r,max(dl,mid),dr,pluse);else pushdown(p<<1|1,mid,r);
            val[p]=val[p<<1]+val[p<<1|1];
            return ;
        }
        void setmulty(int p,int l,int r,int dl,int dr,long long multy)
        {
            if(lazyp[p]!=0||lazym[p]!=1) pushdown(p,l,r);
            if(l==dl&&r==dr)
            {lazyp[p]=(lazyp[p]*multy)%mod,lazym[p]=(lazym[p]*multy)%mod,pushdown(p,l,r);return ;}
            int mid=l+r>>1;
            if(mid>dl) setmulty(p<<1,l,mid,dl,min(mid,dr),multy);else pushdown(p<<1,l,mid);
            if(mid<dr) setmulty(p<<1|1,mid,r,max(dl,mid),dr,multy);else pushdown(p<<1|1,mid,r);
            val[p]=(val[p<<1]+val[p<<1|1])%mod;
            return ;
        }
        int sum(int p,int l,int r,int dl,int dr)
        {
            if(lazyp[p]!=0||lazym[p]!=1) pushdown(p,l,r);
            if(l==dl&&r==dr) return val[p];
            int mid=l+r>>1;int res=0;
            if(mid>dl) res+=sum(p<<1,l,mid,dl,min(dr,mid));
            if(mid<dr) res+=sum(p<<1|1,mid,r,max(dl,mid),dr);
            res%=mod;
            return res;
        }
    
    }lt;
    int n,m,t;
    int u,v,opt;
    signed main()
    {
        scanf("%d%d%d",&n,&m,&mod);
        lt.build(1,0,n);
        for(int i=1;i<=m;i++)
        {
    
            scanf("%d%d%d",&opt,&u,&v);
            if(opt==1) {scanf("%d",&t);lt.setmulty(1,0,n,u-1,v,t);}
            if(opt==2) {scanf("%d",&t);lt.setpluse(1,0,n,u-1,v,t);}
            if(opt==3) {printf("%d
    ",lt.sum(1,0,n,u-1,v));}
        }
        return 0;
    }
  • 相关阅读:
    手写RPC
    随机生成6位的字符串验证码,要求包含数字,大小写字母
    输出学习阶段目标
    吃货联盟
    判断是否为整数
    实现一个登录注册功能
    作业1
    年龄异常
    作业2
    作业1
  • 原文地址:https://www.cnblogs.com/arcturus/p/9253146.html
Copyright © 2011-2022 走看看