• 线段树【模版】


    题目描述

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

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

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

    输入输出格式

    输入格式:

    第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。

    第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

    接下来M行每行包含3或4个整数,表示一个操作,具体如下:

    操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k

    操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和

     

    输出格式:

    输出包含若干行整数,即为所有操作2的结果。

     

    输入输出样例

    输入样例#1: 复制
    5 5
    1 5 4 2 3
    2 2 4
    1 2 3 2
    2 3 4
    1 1 5 1
    2 1 4
    输出样例#1: 复制
    11
    8
    20

    说明

    时空限制:1000ms,128M

    数据规模:

    对于30%的数据:N<=8,M<=10

    对于70%的数据:N<=1000,M<=10000

    对于100%的数据:N<=100000,M<=100000

    (数据已经过加强^_^,保证在int64/long long数据范围内)

    样例说明:

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define N 100002
    int n,m,op,l,r,k;
    struct node{
        int l,r;
        long long lazy,sum;
    }t[4 * N];
    long long a[N];
    void up(int p)
    {
        t[p].sum = t[p * 2].sum + t[p * 2 + 1].sum;    
        return;//
    } 
    void down(int p)
    {
        if(t[p].l == t[p].r||t[p].lazy == 0) return;//
        t[p * 2].lazy += t[p].lazy;
        t[p * 2].sum += t[p].lazy * (t[p * 2].r - t[p * 2].l + 1);
        t[p * 2 + 1].lazy += t[p].lazy;
        t[p * 2 + 1].sum += t[p].lazy * (t[p * 2 + 1].r - t[p * 2 + 1].l + 1);
        t[p].lazy = 0;
    }
    void build(int p,int l,int r)
    {
        t[p].l = l;
        t[p].r = r;
        t[p].lazy = 0;
        if(l == r)
        {
            t[p].sum = a[l];
            return;//要记得返回呀 
        }
        int mid = (l + r) / 2;
        build(p * 2,l,mid);
        build(p * 2 + 1,mid + 1,r);
        up(p);//传值上去 
    }
    void change(int p,int l,int r,long long k)
    {
        down(p);
        if(l == t[p].l && r == t[p].r)
        {
            t[p].sum += (r - l + 1) * k;
            t[p].lazy = k;
            return;
        }
        int mid = (t[p].r + t[p].l) / 2;
        if(mid >= r) change(p * 2,l,r,k);
        else if(mid < l) change(p * 2 + 1,l,r,k);
        else change(p * 2,l,mid,k),change(p * 2 + 1,mid + 1,r,k);
        up(p);
    }
    long long ans(int p,int l,int r)//用long long
    {
        down(p);
        if(l == t[p].l && r == t[p].r)
        {
            return t[p].sum;
        }
        int mid = (t[p].r + t[p].l) / 2;
        if(mid >= r) return ans(p * 2,l,r);
        if(mid < l) return ans(p * 2 + 1,l,r);
        return ans(p * 2,l,mid) + ans(p * 2 + 1,mid + 1,r);//
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i = 1;i <= n;i++)
        {
            scanf("%d",&a[i]);
        }
        build(1,1,n);
        for(int i = 1;i <= m;i++)
        {
            scanf("%d",&op);
            if(op == 1)
            {
                scanf("%d%d%d",&l,&r,&k);
                change(1,l,r,k);
            }
            else{
                scanf("%d%d",&l,&r);
                printf("%lld
    ",ans(1,l,r));
            }
        }
        return 0;
    }
  • 相关阅读:
    Dynamically allocated memory 动态分配内存【malloc】Memory leaks 内存泄漏
    const pointers
    heap是堆,stack是栈
    Java中使用Cookie
    Postman注册、登录、导出、导入
    HttpServletRequest get post 入参
    判断设置的时间是否大于当前时间
    JS回车登录
    一个普通的Ajax
    Java工具类
  • 原文地址:https://www.cnblogs.com/yupeiqi/p/9436944.html
Copyright © 2020-2023  润新知