• 线段树练习


    线段树练习

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

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


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


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

    输入描述

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

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

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

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

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

    输出描述

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

    样例输入

    3

    1

    2

    3

    2

    1 2 3 2

    2 2 3

    样例输出

    9

    数据范围及提示

    1<=n<=200000

    1<=q<=200000

    #include<cstdio>
    int m,n,x,y;
    long long a[200005];
    long long ans,z;
    struct ty{
        int l,r;
        long long data,sum;
    } t[1000005];
    long long buid(int x,int y,int k)
    {
        t[k].l=x;t[k].r=y;
        if(x!=y){
            int q,p;
            q=buid(x,(x+y)/2,2*k);
            p=buid((x+y)/2+1,y,2*k+1);
            t[k].sum=q+p;
            return t[k].sum;
        }
        else return t[k].sum=a[x];
    }
    void updata(int k)
    {
        
        t[k*2].data+=t[k].data;
        t[k*2+1].data+=t[k].data;
        t[k*2].sum+=t[k].data*(t[k*2].r-t[k*2].l+1);
        t[k*2+1].sum+=t[k].data*(t[k*2+1].r-t[k*2+1].l+1);
        t[k].data=0;
        
    }
    int jia(int k,int x,int y,int z)
    {
        if(t[k].l>=x&&t[k].r<=y){
            t[k].data+=z;
            t[k].sum+=z*(t[k].r-t[k].l+1);
        }
        else{
            if(t[k].data!=0) updata(k);
            if(x<=(t[k].l+t[k].r)/2) jia(k*2,x,y,z);
            if(y>(t[k].l+t[k].r)/2) jia(k*2+1,x,y,z);
            t[k].sum=t[k*2].sum+t[k*2+1].sum;
        }    
    }
    long long find(int k,int x,int y)
    {
        if(x<=t[k].l&&y>=t[k].r)    return t[k].sum;
        else{
            if(t[k].data!=0) updata(k);
            long long zh=0;
            if(x<=(t[k].l+t[k].r)/2) zh+=find(k*2,x,y);
            if(y>(t[k].l+t[k].r)/2) zh+=find(k*2+1,x,y);
            return zh;
        }
            
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        buid(1,n,1);
        scanf("%d",&m);
        int g;
        for(int i=1;i<=m;i++) 
        {
            scanf("%d",&g);
            if(g==1) {
                scanf("%d%d%d",&x,&y,&z);
                jia(1,x,y,z);
            }
            else
            {
                scanf("%d%d",&x,&y);
                ans=find(1,x,y);
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    SUSE 安装 iServer、iDesktop启动异常问题
    各系统勒索补丁下载地址
    centos 安装atom 笔记
    转载---SuperMap GIS 9D SP1学习视频播单
    SuSE的命令安装软件 zypper
    Leaflet客户端学习笔记
    设置UI控件的Layer属性(边框可见,边框颜色,边框宽度,边框圆角)
    安全清理Xcode 缓存垃圾
    OC变量命名禁忌
    iOS中的应用启动原理
  • 原文地址:https://www.cnblogs.com/qingang/p/5189091.html
Copyright © 2020-2023  润新知