线段树(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内可通过。清晰明了的线段树数据结构如下。

View Code
 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编辑  收藏  举报

导航