• 线段树练习3


    题目传送:http://codevs.cn/problem/1082/

    1082 线段树练习 3

     

     时间限制: 3 s
     空间限制: 128000 KB
     题目等级 : 大师 Master
     
     
     
    题目描述 Description

    给你N个数,有两种操作:


    1:给区间[a,b]的所有数增加X


    2:询问区间[a,b]的数的和。

    输入描述 Input Description

    第一行一个正整数n,接下来n行n个整数,

    再接下来一个正整数Q,每行表示操作的个数,

    如果第一个数是1,后接3个正整数,

    表示在区间[a,b]内每个数增加X,如果是2,

    表示操作2询问区间[a,b]的和是多少。

    pascal选手请不要使用readln读入

    输出描述 Output Description

    对于每个询问输出一行一个答案

    样例输入 Sample Input

    3

    1

    2

    3

    2

    1 2 3 2

    2 2 3

    样例输出 Sample Output

    9

    数据范围及提示 Data Size & Hint

    数据范围

    1<=n<=200000

    1<=q<=200000

    分类标签 Tags 

     代码

    #include<cstdio>
    #include<iostream>
    using namespace std;
    #define N 801000
    #define mid ((l+r)>>1)
    #define lc (k<<1)
    #define rc (k<<1|1)
    #define ll long long
    ll a[N],tag[N];
    ll read(){
        register ll f=1,x=0;
        register char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    void ins(int k,int l,int r,int i,int val){
        if(l==r){a[k]=val;return;}
        if(i<=mid) ins(lc,l,mid,i,val);
        else ins(rc,mid+1,r,i,val);
        a[k]=a[lc]+a[rc];
    }
    void pushdown(int k,int l,int r){
        if(!tag[k]) return ;
        a[lc]+=tag[k]*(mid-l+1);
        a[rc]+=tag[k]*(r-mid);
        tag[lc]+=tag[k];tag[rc]+=tag[k];tag[k]=0;    
    }
    void add(int k,int l,int r,int x,int y,int val){
        if(l==x&&r==y){
            tag[k]+=val;a[k]+=(r-l+1)*val;return ;
        }
        pushdown(k,l,r);
        if(y<=mid) add(lc,l,mid,x,y,val);
        else if(x>mid) add(rc,mid+1,r,x,y,val);
        else add(lc,l,mid,x,mid,val),add(rc,mid+1,r,mid+1,y,val);
        a[k]=a[lc]+a[rc];
    }
    ll query(int k,int l,int r,int x,int y){
        if(l==x&&r==y) return a[k];
        pushdown(k,l,r);
        if(y<=mid) return query(lc,l,mid,x,y);
        else if(x>mid) return query(rc,mid+1,r,x,y);
        else return (query(lc,l,mid,x,mid)+query(rc,mid+1,r,mid+1,y));    
    }
    int main(){
        ll n=read(),b;
        for(ll i=1;i<=n;i++) b=read(),ins(1,1,n,i,b);
        ll m=read();
        for(ll i=1;i<=m;i++){
            ll opt=read();
            if(opt==1){
                ll l=read(),r=read(),val=read();
                if(l>r) swap(l,r);
                add(1,1,n,l,r,val);
            }
            else{
                ll l=read(),r=read();
                if(l>r) swap(l,r);
                printf("%lld
    ",query(1,1,n,l,r));
            }
        }
        return 0;
    }

     结构体

    (便于维护和修改)

    #include<cstdio>
    struct node{
        int l,r,lch,rch,tage;
        long long sum;
    }tr[401000];
    int a[201000];
    int cnt;
    void build(int k,int l,int r){//不一样的建树 
        cnt++;
        tr[cnt].l=l;tr[cnt].r=r;
        if(l==r){
            tr[cnt].sum=a[l];return ;
        }
        tr[k].lch=cnt+1;
        int mid=(l+r)>>1;
        build(cnt+1,l,mid);
        tr[k].rch=cnt+1;
        build(cnt+1,mid+1,r);
        tr[k].sum=tr[tr[k].lch].sum+tr[tr[k].rch].sum;
    }
    void pushdown(int k){
        if(!tr[k].tage) return ;//下放--维护区 
        tr[tr[k].lch].sum+=tr[k].tage*(tr[tr[k].lch].r-tr[tr[k].lch].l+1);
        tr[tr[k].rch].sum+=tr[k].tage*(tr[tr[k].rch].r-tr[tr[k].rch].l+1);
        tr[tr[k].lch].tage+=tr[k].tage;
        tr[tr[k].rch].tage+=tr[k].tage;
        tr[k].tage=0;
    }
    void add(int k,int x,int y,int v){//在[l,r](初始是[1,n])中找到[x,y]修改 
        int l=tr[k].l,r=tr[k].r;
        if(l<=x&&r>=y){//数据上传(类似updata),更新父节点 
            tr[k].sum+=(y-x+1)*v;
        }
        if(l==x&&r==y){
            tr[k].tage+=v;return ;
        }
        pushdown(k);//数据下传,更新子节点
        int mid=(l+r)>>1;
        if(y<=mid) add(tr[k].lch,x,y,v);
        else if(x>mid) add(tr[k].rch,x,y,v);
        else add(tr[k].lch,x,mid,v),add(tr[k].rch,mid+1,y,v);    
    }
    long long query(int k,int x,int y){//数据范围是long long 
        int l=tr[k].l,r=tr[k].r;
        if(l==x&&r==y) return tr[k].sum;
        pushdown(k);//数据下传,更新子节点
        int mid=(l+r)>>1;
        if(y<=mid) return query(tr[k].lch,x,y);
        else if(x>mid) return query(tr[k].rch,x,y);
        else return query(tr[k].lch,x,mid)+query(tr[k].rch,mid+1,y);
    }
    int main(){int n,m,l,r,v,opt;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",a+i);
        build(1,1,n);
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            scanf("%d",&opt);
            if(opt==1){
                scanf("%d%d%d",&l,&r,&v);
                add(1,l,r,v);
            }
            if(opt==2){
                scanf("%d%d",&l,&r);
                long long ans=query(1,l,r);
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }

     最新版

    #include<cstdio>
    #include<iostream>
    #define ll long long
    #ifdef unix
    #define LL "%lld"
    #else
    #define LL "%I64d"
    #endif
    #define lc k<<1
    #define rc k<<1|1
    using namespace std;
    inline ll read(){
        register ll x=0;bool f=1;
        register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=0;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    const int N=2e5+10;
    const int M=N<<2;
    ll n,m,t1[N],a[M],tag[M];
    void build(ll k,ll l,ll r){
        if(l==r){
            a[k]=t1[l];return ;
        }
        ll mid=l+r>>1;
        build(lc,l,mid);
        build(rc,mid+1,r);
        a[k]=a[lc]+a[rc];
    }
    void pushdown(ll k,ll l,ll r){
        if(!tag[k]) return ;
        tag[lc]+=tag[k];
        tag[rc]+=tag[k];
        ll mid=l+r>>1;
        a[lc]+=tag[k]*(mid-l+1);
        a[rc]+=tag[k]*(r-mid);
        tag[k]=0;
    }
    void ins(ll k,ll l,ll r,ll x,ll y,ll val){
        if(l==x&&r==y){
            a[k]+=(y-x+1)*val;
            tag[k]+=val;
            return ;
        }
        pushdown(k,l,r);
        ll mid=l+r>>1;
        if(y<=mid) ins(lc,l,mid,x,y,val);
        else if(x>mid) ins(rc,mid+1,r,x,y,val);
        else ins(lc,l,mid,x,mid,val),ins(rc,mid+1,r,mid+1,y,val);
        a[k]=a[lc]+a[rc];
    }
    ll query(ll k,ll l,ll r,ll x,ll y){
        if(l==x&&r==y) return a[k];
        pushdown(k,l,r);
        ll mid=l+r>>1;
        if(y<=mid) return query(lc,l,mid,x,y);
        else if(x>mid) return query(rc,mid+1,r,x,y);
        else return query(lc,l,mid,x,mid)+query(rc,mid+1,r,mid+1,y);
    }
    int main(){
        n=read();
        for(ll i=1;i<=n;i++) t1[i]=read();
        build(1,1,n);
        m=read();
        for(ll i=1,opt,x,y,z;i<=m;i++){
            opt=read();
            if(opt==1){
                x=read();y=read();z=read();
                ins(1,1,n,x,y,z);
            }
            else{
                x=read();y=read();
                printf(LL"
    ",query(1,1,n,x,y));
            } 
        }
        return 0;
    }

     可动态插点版

    #include<cstdio>
    using namespace std;
    typedef long long ll;
    int read(){
        int x=0;char ch=getchar();
        while(ch<'0'||ch>'9') ch=getchar();
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 
        return x;
    }
    const int N=2e5+10;
    const int M=N*4;
    int n,a[N];
    int root,sz,ls[M],rs[M],tag[M];
    ll sum[M];
    void updata(int k){
        sum[k]=sum[ls[k]]+sum[rs[k]];
    }
    void pushdown(int k,int l,int r){
        if(!tag[k]||l==r) return ;
        int mid=l+r>>1;
        tag[ls[k]]+=tag[k];
        tag[rs[k]]+=tag[k];
        sum[ls[k]]+=tag[k]*(mid-l+1);
        sum[rs[k]]+=tag[k]*(r-mid);
        tag[k]=0;
    }
    void build(int &k,int l,int r){
        if(!k) k=++sz;
        if(l==r){sum[k]=a[l];return ;}
        int mid=l+r>>1;
        build(ls[k],l,mid);
        build(rs[k],mid+1,r);
        updata(k);
    }
    void change(int k,int l,int r,int x,int y,int val){
        if(l==x&&r==y){
            tag[k]+=val;sum[k]+=(r-l+1)*val;return ;
        }
        pushdown(k,l,r);
        int mid=l+r>>1;
        if(y<=mid) change(ls[k],l,mid,x,y,val);
        else if(x>mid) change(rs[k],mid+1,r,x,y,val);
        else change(ls[k],l,mid,x,mid,val),change(rs[k],mid+1,r,mid+1,y,val);
        updata(k);
    }
    ll query(int k,int l,int r,int x,int y){
        if(l==x&&r==y) return sum[k];
        pushdown(k,l,r);
        int mid=l+r>>1;
        if(y<=mid) return query(ls[k],l,mid,x,y);
        else if(x>mid) return query(rs[k],mid+1,r,x,y);
        else return query(ls[k],l,mid,x,mid)+query(rs[k],mid+1,r,mid+1,y);
    }
    int main(){
        n=read();root=sz=1;//WA*1
        for(int i=1;i<=n;i++) a[i]=read();
        build(root,1,n);
        for(int cas=read();cas--;){
            int opt=read();
            if(opt==1){
                int l=read(),r=read(),val=read();
                change(root,1,n,l,r,val);
            }
            else{
                int l=read(),r=read();
                printf("%lld
    ",query(root,1,n,l,r));
            }
        }
        return 0;
    }

     分块版

    #include<cstdio>
    #include<cmath>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int F=501;
    int n,m,q;
    ll ans,sum[F],tag[F],b[F][F];
    int main(){
        n=read();
        int m=sqrt(n)+1;
        for(int i=0;i<n;i++) b[i/m][i%m]=read();
        for(int i=0;i<m;i++){
            for(int j=0;j<m;j++){
                sum[i]+=b[i][j];
            }
        }
        q=read();
        for(int opt,x,y,z,b1,b2,p1,p2;q--;){
            opt=read();
            if(opt&1){
                x=read()-1;y=read()-1;z=read();
                b1=x/m;b2=y/m;
                p1=x%m;p2=y%m;
                if(b1==b2){
                    for(int i=p1;i<=p2;i++) b[b1][i]+=z;
                    sum[b1]+=(p2-p1+1)*z;
                }
                else{
                    for(int i=p1;i<m;i++) b[b1][i]+=z;
                    sum[b1]+=(m-p1)*z;
                    for(int i=b1+1;i<b2;i++) tag[i]+=z;
                    for(int i=0;i<=p2;i++) b[b2][i]+=z;
                    sum[b2]+=(p2+1)*z;
                }
            }
            else{
                x=read()-1;y=read()-1;ans=0;
                b1=x/m;b2=y/m;
                p1=x%m;p2=y%m;
                if(b1==b2){
                    for(int i=p1;i<=p2;i++) ans+=b[b1][i];
                    ans+=(p2-p1+1)*tag[b1];
                }
                else{
                    for(int i=p1;i<m;i++) ans+=b[b1][i];
                    ans+=(m-p1)*tag[b1];
                    for(int i=b1+1;i<b2;i++) ans+=sum[i]+tag[i]*m;
                    for(int i=0;i<=p2;i++) ans+=b[b2][i];
                    ans+=(p2+1)*tag[b2];
                }
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    一个可以用的Lua的Class函数
    写一个可以用的Lua打印Table的函数
    关于C#的接口的碎碎念
    C#中接口是值类型还是引用类型?
    Effective C++笔记_条款31将文件间的编译依存关系降至最低
    Effective C++ 阅读笔记_条款27 尽量少做转型动作
    Flask--开发全套
    python之元类
    Django之模板层
    go打开文件
  • 原文地址:https://www.cnblogs.com/shenben/p/5459728.html
Copyright © 2020-2023  润新知