以前经常听大佬说“用线段树优化”,然而我连这是什么东西都不知道(。・・)ノ,所以今天特意去学了一下。
线段树是一种二叉树,它的每个节点的值表示一个数组一段区间的最大值(或最小值,以下相同),如果某个节点的表示的数组区间[l,r]内的最大值,那么它的左孩子表示数组区间[l,(l+r)/2]内的最大值,它的右孩子表示数组区间[(l+r)/2+1,r]内的最大值。(这只是我的粗浅理解,如果不对,麻烦大佬提醒一下,谢谢~~)
线段树可以快速地找出数组中某段区间的最大值(或最小值),建立耗时O(n*logn),查询、更新操作耗时O(logn),如果查找的次数比较多的话,比顺序查找快很多。
看了一下午,只会建立和查找,还不会更新线段树,原谅我比较菜.....
线段树的建立和查找:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <ctime>
using namespace std;
typedef struct xxx
{
int valu;
xxx *lchild;
xxx *rchild;
}xxx;
int set_xdtree (int date[], xxx *&p, int l, int r);
int search (xxx *p, int l, int r, int x, int y);
int main()
{
int a[1000] = {156, 68, 65, 98, 64, 37, 1324, 789, 456, 24, 78};
xxx *root, *p;
root = NULL;
set_xdtree (a, root, 0, 10);
cout << search (root, 0, 10, 2, 9);
return 0;
}
//建立线段树
int set_xdtree (int date[], xxx *&p, int l, int r)
{
int a, b;
int mid;
p = new xxx;
if (l >= r)
{
p -> lchild = NULL;
p -> rchild = NULL;
p -> valu = date[l];
return date[l];
}
mid = (l + r) /2;
a = set_xdtree (date, p -> lchild, l, mid);
b = set_xdtree (date, p -> rchild, mid + 1, r);
if (a > b)
{
p -> valu = a;
}
else
{
p ->valu = b;
}
return p -> valu;
}
//查找区间[x,y]内的最大值
int search (xxx *p, int l, int r, int x, int y)
{
int a, b;
int mid;
if (x <= l && y >= r)
{
return p -> valu;
}
mid = (l + r) / 2;
if (mid < x)
{
return search (p -> rchild, mid + 1, r, x, y);
}
if (mid >= y)
{
return search (p -> lchild, l, mid, x, y);
}
a = search (p -> lchild, l, mid, x, mid);
b = search (p -> rchild, mid + 1, r, mid + 1, y);
if (a > b)
{
return a;
}
else
{
return b;
}
}