Implementation:Segment Tree 线段树
早就听人提起过线段树,今天有题搞不出来,讨论上说要用一下线段树,看了下,本质上是空间划分索引,只不过是一维上面的,如果在二维则是四叉树,三维则是八叉树,如果可以动态调整那么跟R-Tree就很相似了,他们都可以对范围查询做出响应。参照书上写了一个,虽然不多,但是渣渣也写的很是费力
#include <iostream>
#include <cstdlib>
#include <vector> using namespace std; class SegmentTree {
private:
int *mem;
int capacity;
int storage_size;
private:
void init_level_update() {
int k = capacity - ;
while (--k >= ) {
int L = (k<<) + ;
int R = L + ;
mem[k]= min(mem[L], mem[R]);
}
} int query(int a, int b, int idx, int L, int R) {
if (b <= L || a >= R) return INT_MAX;
if (a <= L && R <= b) return mem[idx]; int ml = query(a, b, (idx<<) + , L, (L+R)/);
int mr = query(a, b, (idx<<) + , (L+R)/, R);
return min(ml, mr);
} void init_mem(int _capacity) {
if (_capacity <= ) {
capacity = ;
return;
}
int n = ;
while (n < _capacity) n<<=;
capacity = n;
storage_size = capacity * - ;
mem = new int[storage_size]; int k = ;
while (k < storage_size) mem[k++] = INT_MAX;
}
public:
SegmentTree(int _capacity) {
init_mem(_capacity);
}
SegmentTree(vector<int>::iterator begin, vector<int>::iterator end) {
capacity = end - begin;
init_mem(capacity); int k = capacity - ;
vector<int>::iterator iter = begin;
while (iter != end) mem[k++] = *iter++; init_level_update();
}
~SegmentTree() {
delete[] mem;
} // update value in original data index
void update(int idx, int val) {
if (idx >= capacity || idx < ) return;
int k = idx + capacity - ; // internal storage index
mem[k] = val;
while (k > ) {
k = (k - ) >> ;
int L = (k << ) + ;
int R = L + ;
mem[k] = min (mem[L], mem[R]);
}
} // retrive the min value in index range [a, b)
int query(int a, int b) {
return query(a, b, , , capacity);
} void print_mem(const char* msg) {
cout<<msg<<endl;
for (int i=; i<(capacity*-); i++) {
cout<<mem[i]<<" ";
}
cout<<endl;
}
}; void test(const char* msg, SegmentTree& seg_tree, int* data, int size) {
cout<<msg<<endl;
for (int i=; i<=size; i++) {
for (int j=i+; j<=size; j++) {
int tmin = seg_tree.query(i, j);
cout<<"min of ("<<i<<","<<j<<") = "<<tmin<<endl;
int amin = INT_MAX;
for (int k=i; k<j; k++) if (data[k] < amin) amin = data[k];
if (amin != tmin)
cout<<"fail"<<endl;
else
cout<<"ok"<<endl;
}
}
}
int main() {
int h[] = {, , , , , , };
int size= sizeof(h) / sizeof(int);
vector<int> hs(h, h + size); SegmentTree seg_tree(hs.begin(), hs.end());
test("Test construction with data :", seg_tree, h, size); SegmentTree init_empty_tree(size);
for (int i=; i<size; i++) init_empty_tree.update(i, h[i]);
test("Test construction without data", init_empty_tree, h, size); system("pause");
return ;
}
下面是一个带有返回最小值索引值的改进版本
class SegmentTree {
private:
int *mem;
int *idx;
int capacity;
int storage_size;
private:
void init_level_update() {
int k = capacity - ;
while (--k >= ) {
int L = (k<<) + ;
int R = L + ;
if (mem[L] < mem[R]) {
mem[k] = mem[L];
idx[k] = idx[L];
} else {
mem[k] = mem[R];
idx[k] = idx[R];
}
}
}
pair<int, int> query(int a, int b, int idx, int L, int R) {
if (b <= L || a >= R) return make_pair(INT_MAX, -);
if (a <= L && R <= b) return make_pair(mem[idx], this->idx[idx]);
pair<int, int> ml = query(a, b, (idx<<) + , L, (L+R)/);
pair<int, int> mr = query(a, b, (idx<<) + , (L+R)/, R);
return ml.first < mr.first ? ml : mr;
}
void init_mem(int _capacity) {
if (_capacity <= ) {
capacity = ;
return;
}
int n = ;
while (n < _capacity) n<<=;
capacity = n;
storage_size = capacity * - ;
mem = new int[storage_size];
idx = new int[storage_size];
int k = ;
while (k < storage_size) mem[k++] = INT_MAX;
k = capacity - ;
int i = ;
while (k < storage_size) idx[k++] = i++;
}
public:
SegmentTree(int _capacity) {
init_mem(_capacity);
}
SegmentTree(vector<int>::iterator begin, vector<int>::iterator end) {
capacity = end - begin;
init_mem(capacity);
int k = capacity - ;
vector<int>::iterator iter = begin;
while (iter != end) mem[k++] = *iter++;
init_level_update();
}
~SegmentTree() {
delete[] mem;
delete[] idx;
}
// update value in original data index
void update(int index, int val) {
if (index >= capacity || idx < ) return;
int k = index + capacity - ; // internal storage index
mem[k] = val;
while (k > ) {
k = (k - ) >> ;
int L = (k << ) + ;
int R = L + ;
if (mem[L] < mem[R]) {
mem[k] = mem[L];
idx[k] = idx[L];
} else {
mem[k] = mem[R];
idx[k] = idx[R];
}
}
}
// retrive the min value in index range [a, b)
pair<int, int> query(int a, int b) {
return query(a, b, , , capacity);
}
void print_mem(const char* msg) {
cout<<msg<<endl;
for (int i=; i<(capacity*-); i++) {
cout<<mem[i]<<" ";
}
for (int i=; i<capacity * - ; i++) {
cout<<idx[i]<<",";
}
cout<<endl;
}
};
参考:
挑战程序设计竞赛第二版
Implementation:Segment Tree 线段树的更多相关文章
- HDU 4107 Gangster Segment Tree线段树
这道题也有点新意,就是须要记录最小值段和最大值段,然后成段更新这个段,而不用没点去更新,达到提快速度的目的. 本题过的人非常少,由于大部分都超时了,我严格依照线段树的方法去写.一開始竟然也超时. 然后 ...
- SPOJ 11840. Sum of Squares with Segment Tree (线段树,区间更新)
http://www.spoj.com/problems/SEGSQRSS/ SPOJ Problem Set (classical) 11840. Sum of Squares with Segme ...
- 【BZOJ-3165】Segment 李超线段树(标记永久化)
3165: [Heoi2013]Segment Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 368 Solved: 148[Submit][Sta ...
- codeforces 242E - XOR on Segment (线段树 按位数建树)
E. XOR on Segment time limit per test 4 seconds memory limit per test 256 megabytes input standard i ...
- Luogu P4097 [HEOI2013]Segment 李超线段树
题目链接 \(Click\) \(Here\) 李超线段树的模板.但是因为我实在太\(Naive\)了,想象不到实现方法. 看代码就能懂的东西,放在这里用于复习. #include <bits/ ...
- BZOJ.3307.雨天的尾巴(dsu on tree/线段树合并)
BZOJ 洛谷 \(dsu\ on\ tree\).(线段树合并的做法也挺显然不写了) 如果没写过\(dsu\)可以看这里. 对修改操作做一下差分放到对应点上,就成了求每个点子树内出现次数最多的颜色, ...
- HDU 3333 Turing Tree (线段树)
Turing Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- CodeForces 620E New Year Tree(线段树的骚操作第二弹)
The New Year holidays are over, but Resha doesn't want to throw away the New Year tree. He invited h ...
- HDU 3333 Turing Tree 线段树+离线处理
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Othe ...
随机推荐
- python实战——网络爬虫
学习网络爬虫的目的: 1,可以私人定制一个搜索引擎,可以深层次的了解搜索引擎的工作原理. 2,大数据时代,要进行数据分析,首先要有数据源,学习爬虫,可以让我们获取更多的数据. 3,从业人员可以可好的利 ...
- jmeter插件之自定义场景图(万能场景设计)
添加扩展插件 自定义线程组:jp@gc - Ultimate Thread Group 此线程组功能强大,可以实现多种场景设置,添加路径如图 参数含义解释 Start Threads Count:当前 ...
- python3 内置函数详解
内置函数详解 abs(x) 返回数字的绝对值,参数可以是整数或浮点数,如果参数是复数,则返回其大小. # 如果参数是复数,则返回其大小. >>> abs(-25) 25 >&g ...
- 2d旋转(css3实现过度效果和动画效果)
效果: 源码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...
- 简单shell expect程序
1 expect程序 用的Ubuntu,本身没带expect,安装. sudo apt-get install expect (关于expect,参见http://www.tclchina.com/a ...
- django框架--cookie/session
目录 一.http协议无状态问题 二.会话跟踪技术--cookie 1.对cookie的理解 2.cookie的使用接口 3.cookie的属性 4.使用cookie的问题 三.会话跟踪技术--ses ...
- (转)修改及查看mysql数据库的字符集
原文:http://www.cnblogs.com/donqiang/articles/2057972.html Liunx下修改MySQL字符集:1.查找MySQL的cnf文件的位置find / - ...
- (转)Mysql 索引原理及优化
本文内容主要来源于互联网上主流文章,只是按照个人理解稍作整合,后面附有参考链接. 一.摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引 ...
- 《Android应用性能优化》2——内存、CPU、性能测评
4.高效使用内存 4.1 说说内存 Android设备的性能主要取决于以下三因素: CPU如何操纵特定的数据类型: 数据和指令需占用多少存储空间: 数据在内存中的布局 4.2 数据类型 int和lon ...
- 软件级负载均衡器(LVS/HAProxy/Nginx)的特点简介和对比
本文出自 “抚琴煮酒” 博客,出处http://andrewyu.blog.51cto.com/1604432/697466 现在网站发展的趋势对网络负载均衡的使用是随着网站规模的提升根据不同的阶 ...