早就听人提起过线段树,今天有题搞不出来,讨论上说要用一下线段树,看了下,本质上是空间划分索引,只不过是一维上面的,如果在二维则是四叉树,三维则是八叉树,如果可以动态调整那么跟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 线段树的更多相关文章

  1. HDU 4107 Gangster Segment Tree线段树

    这道题也有点新意,就是须要记录最小值段和最大值段,然后成段更新这个段,而不用没点去更新,达到提快速度的目的. 本题过的人非常少,由于大部分都超时了,我严格依照线段树的方法去写.一開始竟然也超时. 然后 ...

  2. SPOJ 11840. Sum of Squares with Segment Tree (线段树,区间更新)

    http://www.spoj.com/problems/SEGSQRSS/ SPOJ Problem Set (classical) 11840. Sum of Squares with Segme ...

  3. 【BZOJ-3165】Segment 李超线段树(标记永久化)

    3165: [Heoi2013]Segment Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 368  Solved: 148[Submit][Sta ...

  4. codeforces 242E - XOR on Segment (线段树 按位数建树)

    E. XOR on Segment time limit per test 4 seconds memory limit per test 256 megabytes input standard i ...

  5. Luogu P4097 [HEOI2013]Segment 李超线段树

    题目链接 \(Click\) \(Here\) 李超线段树的模板.但是因为我实在太\(Naive\)了,想象不到实现方法. 看代码就能懂的东西,放在这里用于复习. #include <bits/ ...

  6. BZOJ.3307.雨天的尾巴(dsu on tree/线段树合并)

    BZOJ 洛谷 \(dsu\ on\ tree\).(线段树合并的做法也挺显然不写了) 如果没写过\(dsu\)可以看这里. 对修改操作做一下差分放到对应点上,就成了求每个点子树内出现次数最多的颜色, ...

  7. HDU 3333 Turing Tree (线段树)

    Turing Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  8. 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 ...

  9. HDU 3333 Turing Tree 线段树+离线处理

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Othe ...

随机推荐

  1. webstorm 调出project

    Alt+1就能弹出窗口面板.    视图-工具窗口-Project 删除项目 Click File > Close project From Recent projects, select pr ...

  2. WebBench源码分析

    源码分析共享地址:https://github.com/fivezh/WebBench 下载源码后编译源程序后即可执行: sudo make clean sudo make & make in ...

  3. springMvc的执行流程(源码分析)

    1.在springMvc中负责处理请求的类为DispatcherServlet,这个类与我们传统的Servlet是一样的.我们来看看它的继承图 2. 我们发现DispatcherServlet也继承了 ...

  4. Lingo 做线性规划 - Operation Management Applications

    Reference: <An Introduction to Management Science Quantitative Approaches to Decision Making, Rev ...

  5. android IPC 机制 (开发艺术探索)

    一.IPC 机制介绍 IPC是Inter-Process Communication的缩写,含义就是进程间通信或者跨进程通信,是指两个进程之间进行数据交换的过程.那么什么是进程,什么是线程,进程和线程 ...

  6. C++的开源跨平台日志库glog学习研究(二)--宏的使用

    上一篇从整个工程上简单分析了glog,请看C++的开源跨平台日志库glog学习研究(一),这一篇对glog的实现代码入手,比如在其源码中以宏的使用最为广泛,接下来就先对各种宏的使用做一简单分析. 1. ...

  7. Apache JMeter2.13 实战

    安装目录下 设置浏览器代理127.0.0.1 8080,以chrome为例 开始录制脚本,进入应用点击相应的功能,可以捕获到如下地址 去除无用地址,保留需要测试的地址 注:上图编号列表中11为获取co ...

  8. CentOS7 yum方式安装 MongoDB 3.4 复制集

    CentOS7 yum方式安装 MongoDB 3.4 环境.准备 Centos7 系统 配置MongoDB的yum源,添加文件/etc/yum.repos.d/mongodb-org-3.4.rep ...

  9. [webpack]path、publicPath、--content-base 理解

    附源码:http://files.cnblogs.com/files/chenshao/startPublic.rar 'use strict'; var webpack = require('web ...

  10. Android 开发服务类 04_ServletForPOSTMethod

    ServletForPOSTMethod 业务类 package com.wangjialin.internet.servlet; import java.io.IOException; import ...