• P3373 【模板】线段树 2


    传送门

    一道板子题,思路和一基本没什么区别只是操作变了。话不多说上代码。

    注意一下:这是大佬交给我们的指针写法,虽然不好理解但是比数组简洁方便容易错

    声明:代码和HwH的线段树一样,因为是他帮我修改的。

    #include<cstdio>
    
    const int maxn=100005;
    int p;
    typedef long long int ll;
    
    int n,q,m;
    ll a[maxn];
    
    struct Node
    {
        ll tag1,tag2,v;
        int l,r;
        Node *ls,*rs;
        inline void maketag1(const ll w,const ll x)
        {
            v+=(r-l+1)%p*w%p;
            tag1=(tag1*x+w)%p;
        }
        inline void maketag2(const ll w)
        {
            v=v%p*w%p;
            tag2=tag2*w%p;
        }
        inline void pushup()
        {
            v=ls->v+rs->v;
            v%=p;
        }
        inline void pushdown()
        {
            if(tag1==0&&tag2==1) return;
            ls->maketag2(tag2);
            ls->maketag1(tag1,tag2);
            rs->maketag2(tag2);
            rs->maketag1(tag1,tag2);
            tag2=1,tag1=0;
        }
        Node(const int L,const int R)
        {
            l=L;r=R;
            if(l==r)
            {
                tag1=0;
                tag2=1;
                v=a[l]%p;
                ls=rs=NULL;
            }
            else
            {
                tag1=0;
                tag2=1;
                ll M=(L+R)>>1;
                ls=new Node(L,M);
                rs=new Node(M+1,R);
                pushup();
            }
        }
        
        inline bool InRange(const int L,const int R) {return (L<=l)&&(r<=R);}
        inline bool OutofRange(const int L,const int R) {return (l>R)||(r<L);}
    
        void upd1(const ll L,const ll R,const ll w)
        {
            if(InRange(L,R))
            {
                maketag1(w,1);
                return;
            }
            else if(!OutofRange(L,R))
            {
                pushdown();
                ls->upd1(L,R,w);
                rs->upd1(L,R,w);
                pushup();
            }
        }
        
        ll qry(const int L,const int R)
        {
            if(InRange(L,R)) return v%p;
            if(OutofRange(L,R)) return 0;
            pushdown();
            return (ls->qry(L,R)+rs->qry(L,R))%p;
        }
        
        void upd2(const int L,const int R,const ll w)
        {
            if(InRange(L,R))
            {
                maketag1(0,w);
                maketag2(w);
                return;
            }
            else if(!OutofRange(L,R))
            {
                pushdown();
                ls->upd2(L,R,w);
                rs->upd2(L,R,w);
                pushup();
            }
        }
    };
    
    int main()
    {
        scanf("%d%d%d",&n,&q,&p);
        for(int i=1;i<=n;++i) scanf("%lld",a+i);
        Node *rot=new Node(1,n);
        for(ll o,x,y,z;q;--q)
        {
            scanf("%lld%lld%lld",&o,&x,&y);
            if(o==1)
            {
                scanf("%lld",&z);
                rot->upd2(x,y,z);
            }
            else if(o==2)
            {
                scanf("%lld",&z);
                rot->upd1(x,y,z);
            }
            else
            {
                printf("%lld
    ",rot->qry(x,y));
            }
        }
        return 0;
    }
     
  • 相关阅读:
    MySql
    Docker
    达观数据
    Python面试题
    用Python构造ARP请求、扫描、欺骗
    git上传简单的命令行分析
    vue2自定义指令的作用
    自定义指令详解 vue
    文档打印 js
    通过Export2Zip实现表格内容下载成为excel文件
  • 原文地址:https://www.cnblogs.com/lizhengde/p/13253270.html
Copyright © 2020-2023  润新知