zoukankan      html  css  js  c++  java
  • 线段树练习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;
    }
  • 相关阅读:
    Hihocoder 1275 扫地机器人 计算几何
    CodeForces 771C Bear and Tree Jumps 树形DP
    CodeForces 778D Parquet Re-laying 构造
    CodeForces 785E Anton and Permutation 分块
    CodeForces 785D Anton and School
    CodeForces 785C Anton and Fairy Tale 二分
    Hexo Next 接入 google AdSense 广告
    如何统计 Hexo 网站的访问地区和IP
    Design and Implementation of Global Path Planning System for Unmanned Surface Vehicle among Multiple Task Points
    通过ODBC接口访问人大金仓数据库
  • 原文地址:https://www.cnblogs.com/shenben/p/5459728.html
Copyright © 2011-2022 走看看