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

    第一种写法

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define I long long
    #define FO(i,a,b) for(R I i=a;i<=b;++i)
    #define fo(i,a,b) for(R I i=a;i<b;++i)
    #define ll long long
    #define ls(x) (x<<1)
    #define rs(x) (ls(x)|1)
    CT I N =100005;
    // CT I M = 200005;
    // const I inf = 2747483647/3;
    using namespace std;
    ll sum[N<<2];
    ll bt[N<<2];
    ll len[N<<2];
    I n,m;
    void down(I son){
        bt[ls(son)]+=bt[son];
        bt[rs(son)]+=bt[son];
        sum[ls(son)]+=bt[son]*len[ls(son)];
        sum[rs(son)]+=bt[son]*len[rs(son)];
        bt[son]=0;
    }
    void insert(I id,I v,I le=1,I re=n,I son=1) {
        if(le==re){
            sum[son]=v;
            len[son]=1;
            return ;
        }
        I mid=(le+re)>>1;
        if (id<=mid) {
            insert(id,v,le,mid,ls(son));
        } else {
            insert(id,v,mid+1,re,rs(son));
        }
        sum[son]=sum[ls(son)]+sum[rs(son)];
        len[son]=len[ls(son)]+len[rs(son)];
    }
    void add(I l,I r,I k,I le=1,I re=n,I son=1){
        if(l<=le&&re<=r){
          sum[son]+=k*len[son];
          bt[son]+=k;
          return ;
        }
        I mid=(le+re)>>1;
        down(son);
        if(l<=mid){add(l,r,k,le,mid,ls(son));}
        if(r>mid){add(l,r,k,mid+1,re,rs(son));}
        sum[son]=sum[ls(son)]+sum[rs(son)];
    }
    ll getsum(I l,I r,I le=1,I re=n,I son=1){
        if(l<=le&&re<=r){
            return sum[son];
        }
        down(son);
        I mid=(le+re)>>1;
        ll ans=0;
        if(l<=mid) ans+=getsum(l,r,le,mid,ls(son));
        if(r>mid) ans+=getsum(l,r,mid+1,re,rs(son));
        return ans;
    }
    int main(){
        scanf("%lld%lld",&n,&m);
        FO(i,1,n){
            I x;
            scanf("%lld",&x);
            insert(i,x);
        }
        FO(i,1,m){
            I x;
            scanf("%lld",&x);
            if (x==1) {
                I l,r,k;
                scanf("%lld%lld%lld",&l,&r,&k);
                add(l,r,k);
            } else {
                I l,r;
                scanf("%lld%lld",&l,&r);
                cout<<getsum(l,r)<<endl;
            }
        }
        return 0;
    }
    

    第二种写法

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define int long long
    inline int ls(int x){return x<<1;}
    inline int rs(int x){return x<<1|1;}
    struct FFF{
        int l,r;
        int sum;
        int tag;
        int mid(){return l+r>>1;}
        int len(){return r-l+1;}
    }t[100000<<2];
    int read(){
        int s,f=1;
        char ch;
        while(!isdigit(ch=getchar()))(ch=='-')&&(f=-1);
        for(s=ch-'0';isdigit(ch=getchar());s=((s+(s<<2))<<1)+ch-'0');
        return s*f;
    }
    int n,m;
    void pushup(int o){
        t[o].sum=t[ls(o)].sum+t[rs(o)].sum;
    }
    void pushdown(int o){
        int & v=t[o].tag;
        t[ls(o)].tag+=v;
        t[rs(o)].tag+=v;
        t[ls(o)].sum+=v*t[ls(o)].len();
        t[rs(o)].sum+=v*t[rs(o)].len();
        v=0;
    }
    void build(int l=1,int r=n,int o=1){
        t[o].l=l;t[o].r=r;
        if(l==r){
            t[o].sum=read();
            return;
        }
        int mid=t[o].mid();
        build(l,mid,ls(o));
        build(mid+1,r,rs(o));
        pushup(o);
    }
    void add(int l,int r,int k,int o=1){
        if(l<=t[o].l&&t[o].r<=r){
            t[o].sum+=k*t[o].len();
            t[o].tag+=k;
            return;
        }
        int mid=t[o].mid();
        pushdown(o);
        if(l<=mid){add(l,r,k,ls(o));}
        if(r>mid){add(l,r,k,rs(o));}
        pushup(o);
    }
    int getsum(int l,int r,int o=1){
        if(l<=t[o].l&&t[o].r<=r){return t[o].sum;}
        pushdown(o);
        int mid=t[o].mid();
        int ans=0;
        if(l<=mid) ans+=getsum(l,r,ls(o));
        if(r>mid) ans+=getsum(l,r,rs(o));
        return ans;
    }
    signed main(){
        n=read();m=read();
        build();
        while(m--){
            int op=read(),l=read(),r=read(),x;
            if(op==1){x=read();add(l,r,x);}
            if(op==2){cout<<getsum(l,r)<<endl;}
        }
        return 0;
    }
    

      

  • 相关阅读:
    java集合 stream 相关用法(1)
    ICE新手入门版
    spring中关于FeignClient的错误 QueryParam.value() was empty on parameter 1
    Java Base64解析
    Java RSA加密以及验签
    项目拆分子工程(简单版)
    mysql "ON DUPLICATE KEY UPDATE" 的使用
    关于多定时任务开发
    AtomicInteger保证线程安全的全局变量
    C++矩阵库 Eigen 快速入门
  • 原文地址:https://www.cnblogs.com/eric-walker/p/9404973.html
Copyright © 2011-2022 走看看