线段树(poj3264)
线段树
实际上还是称为区间树更好理解一些。
树:是一棵树,而且是一棵二叉树。
线段:树上的每个节点对应于一个线段(还是叫“区间”更容易理解,区间的起点和终点通常为整数)
同一层的节点所代表的区间,相互不会重叠。叶子节点的区间是单位长度,不能再分了。
线段树是一棵二叉树,树中的每一个结点表示了一个区间[a,b]。a,b通常是整数。每一个叶子节点表示了一个单位区间。对于每一个非叶结点所表示的结点[a,b],其左儿子表示的区间为[a(a+b)/2],右儿子表示的区间为[(a+b)/2,b](除法去尾取整)。
线段树的特征
1、线段树的深度不超过logL(L是最长区间的长度)。
2、线段树把区间上的任意一条线段都分成不超过2logL条线段。
这些结论为线段树能在O(logL)的时间内完成一条线段的插入、删除、查找等工作,提供了理论依据
线段树的构建
function 以节点v为根建树、v对应区间为[l,r]
{
对节点v初始化
if (l!=r)
{
以v的左孩子为根建树、区间为[l,(l+r)/2]
以v的右孩子为根建树、区间为[(l+r)/2+1,r]
}
}
线段树的基本用途
线段树适用于和区间统计有关的问题。比如某些数据可以按区间进行划分,按区间动态进行修改,而且还需要按区间多次进行查询,那么使用线段树可以达到较快查询速度。
推荐文章:http://poj.org/summerschool/1_interval_tree.pdf
poj3264题,线段树实现,耗时3469MS。可采用rmq等其他算法结合进行优化,1s内可通过。清晰明了的线段树数据结构如下。
1 #include <stdio.h> 2 struct CNode 3 { 4 int L, R; 5 int nMin, nMax; 6 struct CNode *pLeft, *pRight; 7 }; 8 int array[50000+1]; 9 int cur = 0; 10 struct CNode Tree[100000+1]; 11 12 struct CNode* BuildTree(int l, int r) 13 { 14 cur++; 15 int nCur = cur; 16 Tree[nCur].L = l; 17 Tree[nCur].R = r; 18 if(l != r) 19 { 20 Tree[nCur].pLeft = BuildTree(l, (l+r)/2); 21 Tree[nCur].pRight = BuildTree((l+r)/2+1, r); 22 Tree[nCur].nMin = Tree[nCur].pLeft->nMin<Tree[nCur].pRight->nMin ? Tree[nCur].pLeft->nMin : Tree[nCur].pRight->nMin; 23 Tree[nCur].nMax = Tree[nCur].pLeft->nMax>Tree[nCur].pRight->nMax ? Tree[nCur].pLeft->nMax : Tree[nCur].pRight->nMax; 24 } 25 else 26 { 27 Tree[nCur].pLeft = NULL; 28 Tree[nCur].pRight = NULL; 29 Tree[nCur].nMin = array[l]; 30 Tree[nCur].nMax = array[l]; 31 } 32 return &Tree[nCur]; 33 } 34 void GetMinMax(struct CNode *node, int l, int r, int *min, int *max) 35 { 36 if(node->L==l && node->R==r) 37 { 38 if(*min == 0) 39 { 40 *min = node->nMin; 41 } 42 else 43 { 44 *min = node->nMin<*min ? node->nMin : *min; 45 } 46 *max = node->nMax>*max ? node->nMax : *max; 47 return; 48 } 49 if(node->L==node->R && (node->L>r || node->R<l)) 50 { 51 return; 52 } 53 int nMid = (node->L+node->R)/2; 54 if(nMid > r) 55 { 56 GetMinMax(node->pLeft, l, r, min, max); 57 } 58 else if(nMid < l) 59 { 60 GetMinMax(node->pRight, l, r, min, max); 61 } 62 else 63 { 64 GetMinMax(node->pLeft, l, nMid, min, max); 65 GetMinMax(node->pRight, nMid+1, r, min, max); 66 } 67 return; 68 } 69 int main() 70 { 71 int nMin; 72 int nMax; 73 int n; 74 int i; 75 int l, r; 76 int num = 0; 77 struct CNode *node; 78 79 scanf("%d %d", &num, &n); 80 for(i=1; i<=num; ++i) 81 { 82 scanf("%d", &array[i]); 83 } 84 85 node = BuildTree(1, num); 86 for(i=0; i<n; ++i) 87 { 88 scanf("%d %d", &l, &r); 89 nMin = 0; 90 nMax = 0; 91 GetMinMax(node, l, r, &nMin, &nMax); 92 printf("%d\n", nMax-nMin); 93 } 94 return 0; 95 }
posted on 2012-09-04 15:07 favourmeng 阅读(230) 评论(0) 编辑 收藏 举报