zoukankan      html  css  js  c++  java
  • 洛谷——P3373 【模板】线段树 2&& B 数据结构

    P3373 【模板】线段树 2

    题目描述

    如题,已知一个数列,你需要进行下面三种操作:

    1.将某区间每一个数乘上x

    2.将某区间每一个数加上x

    3.求出某区间每一个数的和

    线段树维护区间乘法

    1.如何修改?

      一个数去乘区间里的每一个数,那么这个区间的和会乘以这个数,需要乘法标记,初始化为1,乘法标记要乘以这个数,来下传到他的子树中,即更新他的子区间,当然,他的加法标记也要乘以这个数。

    2.如何更新?

    他子树的值=它的乘法标记*它子树的值+他子树的区间长度*它的加法标记

    乘法标记更新,加法标记更新

    某位大佬的线段树

    #include<bits/stdc++.h>
    #define N 4000000
    #define LL long long
    #define RE register
    #define IN inline 
    
    using namespace std;
    
    IN void in(LL &x){
        RE char c=getchar();x=0;int f=1;
        while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}
        while(isdigit(c)){x=x*10+c-'0';c=getchar();}
        x*=f;
    }
    
    /*
    1.将某区间每一个数乘上x
    
    2.将某区间每一个数加上x
    
    3.求出某区间每一个数的和
    */
    
    LL n,m,X,ans,p;
    struct node{
        LL l,r,w,f,mul;
    }e[N];
    
    IN void build(LL k,LL l,LL r){
        e[k].l=l;e[k].r=r;e[k].mul=1;e[k].f=0;
        if(l==r){
            in(e[k].w);return;
        }LL mid=(l+r)/2;
        build(k*2,l,mid);build(k*2+1,mid+1,r);
        e[k].w=(e[k*2].w+e[k*2+1].w)%p;
    }
    
    IN void down(LL k){
        LL mu=e[k].mul,ll=e[k].l,rr=e[k].r,mid=(ll+rr)/2;
        e[k*2].w=(e[k*2].w*mu+e[k].f*(mid-ll+1))%p;
        e[k*2+1].w=(e[k*2+1].w*mu+e[k].f*(rr-mid))%p;
        
        e[k*2].mul=(e[k*2].mul*mu)%p;
        e[k*2+1].mul=(e[k*2+1].mul*mu)%p;
        
        e[k*2].f=(e[k*2].f*mu+e[k].f)%p;
        e[k*2+1].f=(e[k*2+1].f*mu+e[k].f)%p;
        
        e[k].f=0;e[k].mul=1;
    }
    
    IN void mull(LL k,LL l,LL r){
        LL ll=e[k].l,rr=e[k].r,mid=(ll+rr)/2;
        if(ll>=l&&rr<=r){
            e[k].w=(e[k].w*X)%p;
            e[k].mul=(e[k].mul*X)%p;
            e[k].f=(e[k].f*X)%p;
            return ;
        }if(e[k].f!=0||e[k].mul!=1) down(k);
        if(l<=mid) mull(k*2,l,r);if(r>mid) mull(k*2+1,l,r);
        e[k].w=(e[k*2].w+e[k*2+1].w)%p;
    }
    
    IN void change_LLerval(LL k,LL l,LL r){
        LL ll=e[k].l,rr=e[k].r,mid=(ll+rr)/2;
        if(ll>=l&&rr<=r){
            e[k].f=(e[k].f+X)%p;
            e[k].w=((rr-ll+1)*X+e[k].w)%p;return ;
        }if(e[k].f!=0||e[k].mul!=1) down(k);
        if(l<=mid) change_LLerval(k*2,l,r);if(r>mid) change_LLerval(k*2+1,l,r);
        e[k].w=(e[k*2].w+e[k*2+1].w)%p;
    }
    
    IN void ask_LLerval(LL k,LL l,LL r){
        LL ll=e[k].l,rr=e[k].r,mid=(ll+rr)/2;
        if(ll>=l&&rr<=r){
            ans=(e[k].w+ans)%p;return;
        }if(e[k].f!=0||e[k].mul!=1) down(k);
        if(l<=mid) ask_LLerval(k*2,l,r);if(r>mid) ask_LLerval(k*2+1,l,r);
        e[k].w=(e[k*2].w+e[k*2+1].w)%p;
    }
    
    int main()
    {
        in(n);in(m);in(p);
        build(1,1,n);
        while(m--){
            LL tp,x,y,k;
            in(tp);in(x);in(y);
            if(tp!=3) in(k);
            if(tp==1) X=k,mull(1,x,y);
            else if(tp==2) X=k,change_LLerval(1,x,y);
            else{
                ans=0,ask_LLerval(1,x,y);
                printf("%d
    ",ans);
            }
        }return 0;
    }

    B数据结构

    链接:https://www.nowcoder.com/acm/contest/200/B
    来源:牛客网

    qn姐姐最好了~
    qn姐姐给你了一个长度为n的序列还有m次操作让你玩,
    1 l r 询问区间[l,r]内的元素和
    2 l r 询问区间[l,r]内的元素的平方 和
    3 l r x 将区间[l,r]内的每一个元素都乘上x
    4 l r x 将区间[l,r]内的每一个元素都加上x

    维护区间平方和的值。其他类似吧。。

     
    #include<bits/stdc++.h>
    
    #define N int(1e6)
    #define LL long long
    
    using namespace std;
    
    void in(LL &x) {
        register char c=getchar();
        x=0;
        int f=1;
        while(!isdigit(c)) {
            if(c=='-') f=-1;
            c=getchar();
        }
        while(isdigit(c)) {
            x=x*10+c-'0';
            c=getchar();
        }
        x*=f;
    }
    
    struct node{
        LL l,r,w1,w2,mul,ad;
    }tr[N];
    
    inline void push_up(int k){
        tr[k].w1=tr[k<<1].w1+tr[k<<1|1].w1;
        tr[k].w2=tr[k<<1].w2+tr[k<<1|1].w2;
    }
    
    inline void build(LL k,LL l,LL r){
        tr[k].l=l,tr[k].r=r,tr[k].mul=1;
        if(l==r) {
            in(tr[k].w1);
            tr[k].w2=tr[k].w1*tr[k].w1;
            return;
        }
        LL mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        push_up(k);
    }
    
    inline void push_down(LL k){
        tr[k<<1].w2=tr[k<<1].w2*tr[k].mul*tr[k].mul+tr[k<<1].w1*2*tr[k].ad+(tr[k<<1].r-tr[k<<1].l+1)*tr[k].ad*tr[k].ad;
        tr[k<<1].w1=tr[k<<1].w1*tr[k].mul+tr[k].ad*(tr[k<<1].r-tr[k<<1].l+1);
        tr[k<<1].ad+=tr[k].ad;
        tr[k<<1].mul*=tr[k].mul;
        
        tr[k<<1|1].w2=tr[k<<1|1].w2*tr[k].mul*tr[k].mul+tr[k<<1|1].w1*2*tr[k].ad+(tr[k<<1|1].r-tr[k<<1|1].l+1)*tr[k].ad*tr[k].ad;
        tr[k<<1|1].w1=tr[k<<1|1].w1*tr[k].mul+tr[k].ad*(tr[k<<1|1].r-tr[k<<1|1].l+1);
        tr[k<<1|1].ad+=tr[k].ad;
        tr[k<<1|1].mul*=tr[k].mul;
        
        tr[k].ad=0,tr[k].mul=1;
    }
    
    inline void update_mul(LL k,LL L,LL R,LL w){
        int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
        if(l>=L&&r<=R){
            tr[k].mul*=w;
            tr[k].ad*=w;
            tr[k].w2=w*w*tr[k].w2;
            tr[k].w1=w*tr[k].w1;
            return;
        }
        push_down(k);
        if(L<=mid) update_mul(k<<1,L,R,w);
        if(R>mid) update_mul(k<<1|1,L,R,w);
        push_up(k);
    }
    
    inline void update(LL k,LL L,LL R,LL w){
        int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
        if(l>=L&&r<=R){
            tr[k].w2+=tr[k].w1*2*w+(r-l+1)*w*w;
            tr[k].w1+=w*(r-l+1);
            tr[k].ad+=w;
            return;
        }
        push_down(k);
        if(L<=mid) update(k<<1,L,R,w);
        if(R>mid) update(k<<1|1,L,R,w);
        push_up(k);
    }
    
    LL query1(LL k,LL L,LL R){
        int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
        if(l>=L&&r<=R) return tr[k].w1;
        push_down(k);
        LL an=0; 
        if(L<=mid) an+=query1(k<<1,L,R);
        if(R>mid) an+=query1(k<<1|1,L,R);
        push_up(k);
        return an;
    }
    
    LL query2(LL k,LL L,LL R){
        int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
        if(l>=L&&r<=R) return tr[k].w2;
        push_down(k);
        LL an=0;
        if(L<=mid) an+=query2(k<<1,L,R);
        if(R>mid) an+=query2(k<<1|1,L,R);
        push_up(k);
        return an;
    }
    
    LL n,m;
    
    int main()
    {
        in(n),in(m);
        build(1,1,n);
        for(LL opt,l,r,w,i=1;i<=m;i++){
            in(opt),in(l),in(r);
            if(opt==1){
                printf("%lld
    ",query1(1,l,r));
            }
            if(opt==2){
                printf("%lld
    ",query2(1,l,r));
            }
            if(opt==3){
                in(w);
                update_mul(1,l,r,w);
            }
            if(opt==4){
                in(w);
                update(1,l,r,w);
            }
        }
        return 0;
    }
  • 相关阅读:
    缓动函数速查表
    PHP递归题目
    linux下crontab定时执行本地脚本和定时访问指定url
    jsonp跨域js
    采用PHP函数uniqid生成一个唯一的ID
    php会话(session)生命周期概念介绍及设置更改和回收
    thinkphp3.2 学习
    PDO 查询mysql返回字段整型变为String型解决方法
    apache性能优化
    汉诺塔(四)(暴力)
  • 原文地址:https://www.cnblogs.com/song-/p/9746192.html
Copyright © 2011-2022 走看看