首页 > 其他分享 >线段树入门

线段树入门

时间:2024-07-24 19:40:37浏览次数:6  
标签:10 le 入门 int 线段 value i64 add

【模板】线段树 1

题目描述

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

  1. 将某区间每一个数加上 \(k\)。
  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

样例输入 #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

提示

对于 \(30\%\) 的数据:\(n \le 8\),\(m \le 10\)。
对于 \(70\%\) 的数据:\(n \le {10}^3\),\(m \le {10}^4\)。
对于 \(100\%\) 的数据:\(1 \le n, m \le {10}^5\)。

保证任意时刻数列中所有元素的绝对值之和 \(\le {10}^{18}\)。

【样例解释】

线段树模板:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+9;
using i64 = long long;
struct tree
{
    int l;  // 左儿子
    int r;  // 右儿子
    i64 add;// 懒标记
    i64 value;// 维护的区间内的值
};
i64 arr[MAXN];
tree t[MAXN*4+2];// 记住这里要全初始化为零
void create(int x,int l,int r)
{
    t[x].l=l,t[x].r=r;
    if(l==r)
    {
       t[x].value=arr[l];// 注意这里value是递归返回的
       return ;
    }
    int mid =t[x].l+(t[x].r-t[x].l)/2;
    create(x*2,l,mid);
    create(x*2+1,mid+1,r);
    t[x].value=t[x*2].value+t[x*2+1].value;//递归返回整个区间维护的值
}
void spread(int p)
{
    if(t[p].add!=0)//存在懒标记,那么就把懒标记往下面传递
    {
        t[p*2].value+=(t[p*2].r-t[p*2].l+1)*t[p].add;
        t[p*2+1].value+=(t[p*2+1].r-t[p*2+1].l+1)*t[p].add;
        t[p*2].add+=t[p].add;// 乘二啊我擦!!!
        t[p*2+1].add+=t[p].add;
        // 标记下移,但是只移动一次,能节省时间,待需要的时候再往下移动
        t[p].add=0;
    }
}
void change(int p,int x,int y,int z)//递归返回查询结果
{
    if(x<=t[p].l&&t[p].r<=y)// 注意这个范围,这个区间要完整包含于我ask的区间
    {
        t[p].value+=(t[p].r-t[p].l+1)*z; 
        t[p].add+=z;//代表如果要查询儿子,就必须先把懒标记下移,而这里不下移动,因为本次查询不需要再向下调整了,可以把多次调整转化成一次调整,从而提高调整效率
        return ;
    }
    spread(p);//下移懒标记,这里非常关键

    int mid=(t[p].l+t[p].r)/2;
    if(x<=mid)
    {
        change(p*2,x,y,z);//change的时候x y 是选中的范围,这个是不能改的
    }
    if(y>mid)
    {
        change(p*2+1,x,y,z);
    }
    t[p].value=t[p*2].value+t[p*2+1].value;
}
i64 ask(int p,int x,int y)
{
    if(x<=t[p].l&&y>=t[p].r)return t[p].value;
    spread(p); //这里也要下传懒标记,千万别忘了,如果是查询或者修改子数组,首先要下放懒标记
    i64 ans=0;
    int mid =(t[p].l+t[p].r)/2;
    if(x<=mid)ans+=ask(p*2,x,y);//同理,ask 的时候也不能改!
    if(y>mid) ans+=ask(p*2+1,x,y);
    return ans;
}
int main()
{
    int n,m;
    std::cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        std::cin>>arr[i];
    }
    create(1,1,n);
    for(int i=1;i<=m;i++)
    {
        int t;
        std::cin>>t;
        if(t==1)
        {
            int a,b,c;
            std::cin>>a>>b>>c;
            change(1,a,b,c);
        }
        else
        {
            int x,y;
            std::cin>>x>>y;
            i64 ans= ask(1,x,y);
            cout<<ans<<'\n';
        }
    }
    return 0;
}

这里放一下链接:

大佬的线段树讲解

标签:10,le,入门,int,线段,value,i64,add
From: https://www.cnblogs.com/cxjy0322/p/18321558

相关文章

  • Java学习 - Springboot 集成 Security 入门小实例
    前言SpringSecurity是Spring家族中一个强大可定制的身份验证和访问控制框架,和Shiro一样,它们都具有认证、授权、加密等用于权限管理的功能。但相比于Shiro,SpringSecurity的功能无疑更加强大。而且作为Spring家族中的一份子,配合家族中的其它兄弟-SpringBoot、S......
  • Python基础入门(六)
    Python基础入门(六)一、本节目标掌握文件的概念和操作:文本文件、CSV文件综合案例:奖励富翁系统、汽车租聘系统二、文件介绍文件是计算机中用于存储数据的一种载体,一般存储在磁盘上文件通过以一定的格式和结构存储数据,可以包含文本、图像、音频、视频等各种类型的信息文件在......
  • 音视频入门基础:PCM专题(3)——使用Audacity工具分析PCM音频文件
     =================================================================音视频入门基础:PCM专题系列文章:音视频入门基础:PCM专题(1)——使用FFmpeg命令生成PCM音频文件并播放音视频入门基础:PCM专题(2)——使用Qt播放PCM音频文件音视频入门基础:PCM专题(3)——使用Audacity工具分析PC......
  • webpack入门最简单的demo
    1、在空文件夹下npminit-y2、npminstall--save-devwebpack3、新建src文件夹,在src里新建index.html,写入:<!DOCTYPEhtml><htmllang="en"><head><metacharset="utf-8"><title>WebpackDemo</title></hea......
  • Linux 下的项目开发:从入门到精通
    在Linux系统上开发项目是一种常见且高效的实践。Linux提供了强大的工具和环境,使得开发过程更加流畅。本文将带你了解如何在Linux下进行项目开发,从环境搭建到代码管理,再到最终的部署。一、环境搭建1.1安装Linux发行版首先,你需要一个Linux系统。有许多流行的发行版......
  • [第一章 web入门]SQL注入-1
    [第一章web入门]SQL注入-1payload/index.php?id=1'and0unionselect1,2,group_concat(fllllag)fromfl4g--+?id=-1'unionselect1,2,group_concat(fllllag)fromflag--+Step库名?id=-1'unionselect1,2,group_concat(SCHEMA_NAME)frominformati......
  • 线段树扩展学习
    前言来补一下暑期集训的坑。正文标记可持久化这个很好理解,在进行区间修改的时候,不下传懒标记,查询的时候直接对每一层再进行处理即可。这个主要用于线段树分治,所以理解就行,代码不给了。动态开点之前一直不太会,现在来补一下。这种线段树主要用于优化空间复杂度。就是对于下......
  • SPI协议——结合百问网STM32入门 STM32 HAL快速入门与项目实战视频
    目录1、SPI协议的概念2、SPI的传输模式2.1SPI工作模式2.2SPI传输模式2.3SPI操作方法3、时序图4、代码实现4.1SPIHAL库编程4.2中断方式4.3DMA方式函数说明5、总结5.1SPI协议的优点5.2SPI协议的缺点1、SPI协议的概念SPI(SerialPeripheralInterface,......
  • 线段树(区间操作,例题:洛谷P3372 线段树 1)
    在上一节线段树(原理、构造和区间查询,例题:BalancedLineup)中介绍了线段树的构造,下面就来说一下它的区间操作。区间操作与Lazy-Tag有关,如果修改操作是对区间内的每个元素一一修改,就会比较繁琐低效,目前的解决办法是线段树的tree[i].data记录的是区间i的值(详细见上节),可以再定义一......
  • 逆向分析学习入门教程(非常详细)零基础入门到精通,看这一篇就够了!_逆向都要学啥
    前沿从本篇起,逆向工厂带大家从程序起源讲起,领略计算机程序逆向技术,了解程序的运行机制,逆向通用技术手段和软件保护技术,更加深入地去探索逆向的魅力。一、程序如何诞生?1951年4月开始在英国牛津郡哈维尔原子能研究基地正式投入使用的英国数字计算机“哈维尔·德卡特伦”,是......