线段树
参考资料:
[1]:https://yq.aliyun.com/articles/252586
[2]:挑战程序设计竞赛
目录:
- 相关概念以及性质
- 单点更新
- 区间更新
- 线段树+扫描线算法求矩阵面积
- 基于线段树的RMQ问题
自学笔记:
1,2,3,4:
pdf 提取码:ccu4
5.基于线段树的RMQ问题
根据节点中维护的数据的不同,线段树可以提供不同的功能。
例如:
(1):RMQ问题
(2):在log(n)时间内完成区间查询,区间修改问题
(3):可以用来维护其他数据结构,比如树链剖分就可以用线段树维护轻重链
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ls(x) ((x)<<1) 4 #define rs(x) ((x)<<1 | 1) 5 const int maxn=1e5+50; 6 7 int n; 8 int a[maxn]; 9 struct Node 10 { 11 int l; 12 int r; 13 int val;//存储不同的数据可以对应不同的功能 14 int mid(){ 15 return l+((r-l)>>1); 16 } 17 }segTree[4*maxn];//线段树所开辟的空间一般是原数据的四倍 18 19 void pushUp(int pos)//想上更新 20 { 21 //每个节点的val值存储的是当前区间的最大值 22 segTree[pos].val=max(segTree[ls(pos)].val,segTree[rs(pos)].val); 23 } 24 void buildTree(int l,int r,int pos)//建树 25 { 26 segTree[pos].l=l,segTree[pos].r=r; 27 if(l == r) 28 { 29 segTree[pos].val=a[l]; 30 return ; 31 } 32 int mid=l+((r-l)>>1); 33 buildTree(l,mid,ls(pos)); 34 buildTree(mid+1,r,rs(pos)); 35 pushUp(pos); 36 } 37 /** 38 区间查询分成三种可能的区间 39 1 都在左儿子这个区间 40 2 都在左儿子这个区间 41 3 都在左儿子这个区间 42 **/ 43 int Query(int a,int b,int pos) 44 { 45 if(segTree[pos].l == a && segTree[pos].r == b) 46 return segTree[pos].val; 47 int mid=segTree[pos].mid(); 48 if(b <= mid)//都在左儿子这个区间 49 return Query(a,b,ls(pos)); 50 else if(a > mid)//都在左儿子这个区间 51 return Query(a,b,rs(pos)); 52 else//都在左儿子这个区间 53 return max(Query(a,mid,ls(pos)),Query(mid+1,b,rs(pos))); 54 } 55 void Solve() 56 { 57 buildTree(1,n,1); 58 int a,b; 59 while(scanf("%d%d",&a,&b))//查询区间[a,b]的最大值 60 printf("%d\n",Query(a,b,1)); 61 } 62 int main() 63 { 64 scanf("%d",&n); 65 for(int i=1;i <= n;++i) 66 scanf("%d",a+i); 67 Solve(); 68 return 0; 69 } 70 71 基于线段树的RMQ
代码模板: