【C++】线段树(一)

 【引入】

【问题】

 一个有n个数的序列,进行q次提问:第x到第y个数字(包括x,y)的总和。

在没学线段树之前,我们首先想到的肯定是遍历第x到第y个数,再把它们的和相加。

就像这样:

#include<bits/stdc++.h>
using namespace std;
int num[1000000],n,q,x,y;
int main(){
	cin>>n>>q;
	for(int i=1;i<=n;i++)cin>>num[i];
	for(int i=1;i<=q;i++){
		cin>>x>>y;
		long long ans=0;
		for(int j=x;j<=y;j++)ans+=num[j];
		cout<<ans<<endl;
	}
}

但n,q大于一定范围就会超时。所以就要用到线段树。

【概念】

线段树其实是一种树形数据结构。回到刚才的问题,如果有一种结构能贮存所有x到y的和,当问的时候直接调用就好了。于是我就想到了二叉树,比如一个{1,2,3,4,5,6,7,8,9}的序列根节点用来储存1~9左子树右子树分别贮存1~5和5~9,以此类推(如下图)。

                1~9SUM:45
                 /       \
                /         \
          1~5SUM:15        6~9SUM:30
            /   \             /     \
           /     \           /       \
     1~3SUM:6   4~5SUM:9  6~7SUM:13  8~9SUM:17
        /  \       /  \      /  \       /   \
       /    \     /    \    /    \     /     \
  1~2SUM:3   3   4      5  6      7   8       9
     /  \
    /    \
   1      2
      

【建树(build)】

我们用一维数组来储存这棵二叉树,观察上图不难发现:如果父节点为k那么左节点2k

右子节点为2k+1,所以在最坏情况下一维数组的大小是序列的4倍。用递归建树。

/*SUM是用于存贮二叉树的一维数组,num是序列*/
void Build(int l,int r,int k)
{
    if(l==r){SUM[k]=num[l];return;}//边界条件
    int mid=(l+r)/2;
    Build(l,mid,2*k);//建立右子树
    Build(mid+1,r,2*k+1);//建立左子树
    SUM[k]=SUM[2*k]+SUM[2*k+1];
}

【查找(find)】

树建完了,那要如何访问呢?用递归遍历树,返回总和。

int Find(int l,int r,int k,int ll,int rr)//ll,rr分别指x,y
{
   if(ll<=l&&r<=rr) return SUM[k];//边界条件,访问区间包括当前区间返回该和。
   int mid=(l+r)/2,sum=0;
   if(ll<=mid) sum+=Find(l,mid,2*k,ll,rr);
   if(rr>=mid+1) sum+=Find(mid+1,r,2*k+1,ll,rr);
   return sum;
}

【C++】线段树(二)

相关推荐

  1. C++】线段

    2024-02-16 21:02:01       60 阅读
  2. 决斗(线段

    2024-02-16 21:02:01       52 阅读
  3. 风信子(线段

    2024-02-16 21:02:01       53 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-16 21:02:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-16 21:02:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-02-16 21:02:01       82 阅读
  4. Python语言-面向对象

    2024-02-16 21:02:01       91 阅读

热门阅读

  1. STM32入坑

    2024-02-16 21:02:01       50 阅读
  2. leetcode 152.乘积最大子数组

    2024-02-16 21:02:01       46 阅读
  3. Vue2源码梳理:render函数的实现

    2024-02-16 21:02:01       48 阅读
  4. CSS之BFC

    CSS之BFC

    2024-02-16 21:02:01      47 阅读
  5. Leetcode-709.转换成小写字母

    2024-02-16 21:02:01       54 阅读
  6. Attention Is All Your Need论文笔记

    2024-02-16 21:02:01       59 阅读
  7. C++虚函数

    2024-02-16 21:02:01       53 阅读
  8. gradient accumulate举例子解释

    2024-02-16 21:02:01       55 阅读
  9. 2024.2.6

    2024.2.6

    2024-02-16 21:02:01      52 阅读
  10. 10-通用类型、特质和生命周期

    2024-02-16 21:02:01       49 阅读