线段树(点修改)

线段树是一种数据结构……有了线段树,我们就可以对一个序列进行快速修改并查询某个区间内的最大值、最小值、和等……下面我来说一下线段树是如何实现的

线段树就是一棵二叉树,我们对一棵二叉树上的点依次编号,从根节点开始,我们从1开始编号,然后对于每一层的点从左到右编号,这样我们不难发现有一个很重要的性质,就是对于任意一个非叶子节点,他的左儿子的编号一定是这个节点乘2,右儿子就是这个节点的编号乘2加1。

我对于每一个节点中储存这个节点的所有的儿子节点的最大值、最小值、和,那么我们就一定可以在log(n)的时间内对于要修改的点进行更新,或者对于某个区间进行查询。

线段树一开始肯定感觉有点乱,但最主要的还是看看代码,好好研究一下代码是怎么写的,然后慢慢理解……我是在学了C++半年之后才开始学线段树的……我一开始反正没懂……

代买如下(这就是对于一个序列的点修改和区间查询的代码):

 1 #include<iostream>
 2 #define maxn 1000000
 3 #define INF 2000000000
 4 using namespace std;
 5 int a[maxn],maxv[3*maxn],minv[3*maxn],sumv[3*maxn];
 6 void build(int L,int R,int o)
 7 {
 8     if(L==R)maxv[o]=minv[o]=sumv[o]=a[L];
 9     else
10     {
11         int m=L+(R-L)/2,lc=o<<1,rc=lc+1;
12         build(L,m,lc);
13         build(m+1,R,rc);
14         maxv[o]=max(maxv[lc],maxv[rc]);
15         minv[o]=min(minv[lc],minv[rc]);
16         sumv[o]=sumv[lc]+sumv[rc];
17     }
18     return;
19 }
20 int x,v;
21 void update(int L,int R,int o)
22 {
23     if(L==R)maxv[o]=minv[o]=sumv[o]=v;
24     else
25     {
26         int m=L+(R-L)/2,lc=o<<1,rc=lc+1;
27         if(x<=m)update(L,m,lc);
28         if(x>m)update(m+1,R,rc);
29         maxv[o]=max(maxv[lc],maxv[rc]);
30         minv[o]=min(minv[lc],minv[rc]);
31         sumv[o]=sumv[lc]+sumv[rc];
32     }
33 }
34 int ql,qr,_max,_min,_sum;
35 void query(int L,int R,int o)
36 {
37     if(ql<=L&&R<=qr)
38     {
39         _max=max(_max,maxv[o]);
40         _min=min(_min,minv[o]);
41         _sum+=sumv[o];
42     }
43     else 
44     {
45         int m=L+(R-L)/2,lc=o<<1,rc=lc+1;
46         if(ql<=m)query(L,m,lc);
47         if(qr>m)query(m+1,R,rc);
48     }
49     return;
50 }
51 int main()
52 {
53     int n,Q;
54     scanf("%d",&n);
55     for(int i=1;i<=n;i++)
56     {
57         scanf("%d",&a[i]);
58     }
59     build(1,n,1);
60     scanf("%d",&Q);
61     while(Q--)
62     {
63         char t;
64         scanf("%s",&t);
65         if(t=='Q')
66         {
67             _sum=0;
68             _min=-1u>>1;
69             _max=1<<31;
70             scanf("%d%d",&ql,&qr);
71             query(1,n,1);
72             printf("MaxNum: %d, MinNum: %d, Sum: %d\n",_max,_min,_sum);
73         }
74         if(t=='C')
75         {
76             scanf("%d%d",&x,&v);
77             update(1,n,1);
78         }
79     }
80 }

 

posted @ 2016-02-27 12:09  543~  阅读(644)  评论(0编辑  收藏  举报