树——用二叉树构建线段树

上一博文线段树问题中,用数组表示线段树,成功AC了,本文用二叉树表示线段树,复习一下二叉树,不过下面这段用二叉树代码表示的线段树是无法AC的,因为这个代码的空间复杂度远高于上一个用结构体数组表示的空间复杂度。

#include<iostream>

#include<cstdlib>

#include<algorithm>

#include<vector>

#include<list>

#include<iterator>

#include<string>

#include<stack>

using namespace std;

#define INF 0x3fffffff

struct NODE {

int left, right, value;

};

struct Tree {

NODE node;

Tree *left, *right;

};

class SegTree {

public:

SegTree() {

}

~SegTree() {

}

void Build(Tree *t,int n,int left,int right);

int Find(Tree *t, int n, int begin, int end);

void Update(Tree *t, int n, int ind, int val);

void Destory(Tree *t);

};

void SegTree::Build(Tree *t, int n, int left,int right){

t->node.left = left;

t->node.right = right;

if (left == right)

{

scanf("%d", &t->node.value);

return;

}

int mid = (left + right) >> 1;

t->left = new Tree();

Build(t->left,n << 1, left, mid);

t->right = new Tree();

Build(t->right,(n << 1) + 1, mid + 1, right);

t->node.value = min(t->left->node.value, t->right->node.value);

}

int SegTree::Find(Tree *t,int n, int begin, int end) {

int p1 = INF, p2 = INF;

if (t->node.left >= begin&&t->node.right <= end)

return t->node.value;

if (begin <= t->left->node.right)

p1 = Find(t->left,n << 1, begin, end);

if (end >= t->right->node.left)

p2 = Find(t->right,(n << 1) + 1, begin, end);

return min(p1, p2);

}

void SegTree::Update(Tree *t,int n, int ind, int val) {

if (t->node.left == t->node.right)

{

t->node.value = val;

}

else

{

if (ind <= t->left->node.right)

Update(t->left,n << 1, ind, val);

if (ind >= t->right->node.left)

Update(t->right,(n << 1) + 1, ind, val);

t->node.value = min(t->left->node.value, t->right->node.value);

}

}

void SegTree::Destory(Tree *t) {

Destory(t->left);

Destory(t->right);

delete t;

t = NULL;

}

int main()

{

int N;

int m;

int s, l, r;

SegTree st;

Tree *t = new Tree();

while (~scanf("%d", &N))

{

st.Build(t,1, 0, N - 1);

scanf("%d", &m);

for (int i = 0; i < m; i++)

{

scanf("%d %d %d", &s, &l, &r);

if (s == 0)

printf("%d\n", st.Find(t,1, l - 1, r - 1));

if (s == 1)

st.Update(t,1, l - 1, r);

}

}

st.Destory(t);

return 0;

}

时间: 2024-11-02 09:56:21

树——用二叉树构建线段树的相关文章

树状数组与线段树

一:树状数组 树状数组是对一个数组改变某个元素和求和比较实用的数据结构.两中操作都是O(logn). 需求:有时候我们需要频繁地求数组的前k项和或者求数组从小标i到j的和,这样每次最坏情况下的时间复杂度就会为O(N),这样效率太低了.而树状数组主要就是为了解决这样一个问题.树状数组在求和及修改都可以在O(lgN)时间内完成. 树状数组需要额外维护一个数组,我们设为C[N],原数组为A[N], 其中每个元素C[i]表示A[i-2^k+1]到A[i]的和,这里k是i在二进制时末尾0的个数.注意通过位

HDU 1166 —— 敌兵布阵 【树状数组 or 线段树】

http://acm.hdu.edu.cn/showproblem.php?pid=1166 需求: 1.点修改 2.区间求和 标准的BIT(二叉索引树,又名树状数组)问题,当然也可以用最基础的仅支持“点修改”的线段树来解决! 线段树版本: #include <cstdio> #include <iostream> #define INF 0x3f3f3f3f using namespace std; const int MAXN = 65536 + 5; // 65536 是最小

主席树(可持久化线段树) 静态第k大

可持久化数据结构介绍 可持久化数据结构是保存数据结构修改的每一个历史版本,新版本与旧版本相比,修改了某个区域,但是大多数的区域是没有改变的, 所以可以将新版本相对于旧版本未修改的区域指向旧版本的该区域,这样就节省了大量的空间,使得可持久化数据结构的实现成为了可能. 如下图,就是可持久化链表 插入前 插入后 尽可能利用历史版本和当前版本的相同区域来减少空间的开销. 而主席树(可持久化线段树)的原理同样是这样. 有n个数字,  我们将其离散化,那么总有[1,n]个值,如果建一棵线段树,每个结点维护子

浅谈二维中的树状数组与线段树

一般来说,树状数组可以实现的东西线段树均可胜任,实际应用中也是如此.但是在二维中,线段树的操作变得太过复杂,更新子矩阵时第一维的lazy标记更是麻烦到不行. 但是树状数组在某些询问中又无法胜任,如最值等不符合区间减法的询问.此时就需要根据线段树与树状数组的优缺点来选择了. 做一下基本操作的对比,如下图. 因为线段树为自上向下更新,从而可以使用lazy标记使得矩阵的更新变的高校起来,几个不足就是代码长,代码长和代码长. 对于将将矩阵内元素变为某个值,因为树状数组自下向上更新,且要满足区间加法等限制

poj 3237 Tree(树链剖分,线段树)

Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 7268   Accepted: 1969 Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with

bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)

3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1272  Solved: 451[Submit][Status][Discuss] Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1. 设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先. 有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[

3110: [Zjoi2013]K大数查询 树状数组套线段树

3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1384  Solved: 629[Submit][Status] Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. Input 第一行N,M接下来M行,每行形如1 a b c或2 a b

bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)

1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 10677  Solved: 4313[Submit][Status][Discuss] Description 一 棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值

[BZOJ 3196] 213平衡树 【线段树套set + 树状数组套线段树】

题目链接:BZOJ - 3196 题目分析 区间Kth和区间Rank用树状数组套线段树实现,区间前驱后继用线段树套set实现. 为了节省空间,需要离线,先离散化,这样需要的数组大小可以小一些,可以卡过128MB = = 嗯就是这样,代码长度= =我写了260行......Debug了n小时= = 代码 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #in