【数据结构】线段树入门

线段树是一种二叉搜索树。

它将一个区间划分成一些子区间,每个子区间对应线段树中的一个叶节点。

对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)>>1],右儿子表示的区间为[(a+b)>>1+1,b]。也就是说线段树是一棵平衡二叉树。

下图是对于[1,10]的区间构造的一棵线段树。

线段树的基本操作函数有三个。

分别是build(建树),update(更新),query(查询区间和)。

线段树定义:

struct node{
    int left,right;    //左子树和右子树
    int sum;    //节点区间和
}tree[MAX_N];

线段树建树:

void build(int l,int r,int num)
{
    tree[num].left=l;
    tree[num].right=r;
    if(l==r) return;    //叶子节点
    int mid=(l+r)>>1;    //二分建树
    build(l,mid,num<<1);    //递归建立左子树
    build(mid+1,r,num<<1|1);    //递归建立右子树
} 

线段树更新:

void update(int l,int r,int value,int num)
{
    //叶子节点
    if(tree[num].left==tree[num].right)
        return;
    int mid=(tree[num].left+tree[num].right)>>1;
    //如果所要更新的点的右端小于mid或左端点大于mid,则直接更新l到r的值
    if(r<=mid) update(l,r,value,num<<1);
    else if(l>mid) update(l,r,value,num<<1|1);
    //如果要更新的点在mid两边,则两边分别更新
    else{
        update(l,mid,value,num<<1);
        update(mid+1,r,value,num<<1|1);
    }
} 

线段树查询:

int query(int l,int r,int num)
{
    //叶子节点
    if(l==tree[num].left && r==tree[num].right) return tree[num].sum;
    int mid=(tree[num].left+tree[num].right)>>1;
    //和更新类似
    if(r<=mid) return query(l,r,num<<1);
    if(l>mid) return query(l,r,num<<1|1);
    else return query(l,mid,num<<1)+query(mid+1,r,num<<1|1);
}

线段树应用:连续区间动态查询,连续区间统计等。

时间复杂度:基本保证每个操作为O(logN)。

时间: 2024-10-11 04:19:01

【数据结构】线段树入门的相关文章

hiho1080 - 数据结构 线段树(入门题,两个lazy tag)

题目链接 维护区间和,两个操作:一个是将某个区间设置成一个值,一个是将某个区间增加一个固定值 /**************************************************************/ 每走到一个区间就把lazy tag下放.下放的时候注意顺序! #include <cstdio> #include <cstring> const int N = 100100; struct NODE{ int l,r; int sum; int setTo,

《数据结构》线段树入门(二)

今天继续介绍——线段树之延迟标记 接上期<数据结构>线段树入门(一):http://www.cnblogs.com/shadowland/p/5870339.html 在上期介绍了线段树的最基本内容(线段树单点修改,区间查询),这次将介绍:区间修改,区间查询. Question: 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. 输入描述: 第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,每行表示操作的个数,如果第一数是1,后接3个正

《数据结构》线段树入门(一)

今天介绍一种非常特殊的数据结构——线段树 首先提出一个问题: 给你n个数,有两种操作: 1:给第i个数的值增加X 2:询问区间[a,b]的总和是什么? 输入描述 输入文件第一行为一个整数n,接下来是n行n个整数,表示格子中原来的整数.接下一个正整数q,再接 下来有q行,表示q个询问,第一个整数表示询问代号,询问代号1表示增加,后面的两个数x和A表示给 位置X上的数值增加A,询问代号2表示区间求和,后面两个整数表示a和b,表示要求[a,b]之间的区间和. 样例输入 4 7 6 3 5 2 1 1

线段树入门小结

QUE:线段树? 称谓: 从刘汝佳的书中得知,"这种数据结构在学术界没有统一的术语,但线段树是最常见的叫法.其他叫法包括区间树(interval tree).范围树(range tree)等,但这些属于在特定的场合(如计算几何)中有着特殊的意义".怎么叫看读者的心情,以下统一用线段树称呼. 先来作一些了解: 线段树是一棵二叉树,它的左右儿子也都是一棵线段树.(定义) 线段树也叫区间树,为什么叫它区间树呢?因为线段树是一种基于区间的数据结构. 线段树的每个节点代表一个区间 [L,R],其

线段树入门(Billboard)

Billboard Time Limit:8000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description At the entrance to the university, there is a huge rectangular billboard of size h*w (h is its height and w is its width). The board is the place where

线段树入门(I Hate It)

I Hate It Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问.当然,老师有时候需要更新某位同学的成绩. Input 本题目包含多组测试,请处理到文件结束. 在每个测试的第一行,

线段树入门理解

在复习算法至分治法时,书本上主要介绍了合并排序和快速排序,较为简单.特拓展简单学习一个应用了分治法的算法结构--线段树. acm刷题时遇到许多连续区间的动态查询问题,例如求取某一区间上元素之和.求取某一区间上元素的最大值,此时如果使用一般的方法求解会使得时间超出要求.此时需要使用到线段树,其主要用于高效解决连续区间的动态查询问题. 线段树,类似区间树,是一个完全二叉树,它在各个节点保存一条线段(数组中的一段子数组),由于二叉结构的特性,它基本能保持每个操作的复杂度为O(lgN),从而大大减少耗时

HDU 4902 Nice boat(数据结构-线段树)

Nice boat Problem Description There is an old country and the king fell in love with a devil. The devil always asks the king to do some crazy things. Although the king used to be wise and beloved by his people. Now he is just like a boy in love and c

Chapter 3. 数据结构 线段树

Chapter 3. 数据结构 线段树 Sylvia's I.单点修改,区间查询. 模板: //单点修改 区间求和 //1操作 单点修改//2操作 区间求和 #include<cstdio> #include<iostream> using namespace std; #define MAXN 500005 int sum[MAXN<<2]; int n,m; void PushUp(int rt){//求和 sum[rt]=sum[rt<<1]+sum[

hdu1166敌兵布阵&amp;&amp;hdu1754I Hate It(线段树入门)

单点更新是最最基础的线段树,只更新叶子节点,然后把信息用pushup这个函数更新上来. http://acm.hdu.edu.cn/showproblem.php?pid=1166 update单点更新,query区域求和. #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #define N 200001 using namespace std; s