标签:集合 时间 details -- 代码 为什么 问题 随机 算法思想
1.定义
#include <iostream> #include <cstdio> #define maxn 500000 using namespace std; struct tree { int l,r; long long w; int lazy; }tr[maxn*4];
//l,r代表左右子树,w代表区间的值(每个节点的值),lazy自有用处---详细见后
1 void build(int l,int r,int k) 2 { 3 tr[k].l=l; 4 tr[k].r=r; 5 if(l==r) 6 { 7 scanf("%d",&tr[k].w); 8 return; 9 } 10 int mid=(l+r)/2; 11 build(l,mid,k*2); 12 build(mid+1,r,k*2+1); 13 tr[k].w=tr[k*2].w+tr[k*2+1].w; 14 }
此处mid的使用就体现了二分思想
再次我给一个例子:将1--10建成一个线段树--如图(更好理解)
记住--线段树只是一个数据结构,它的每一个节点都是一个区间(相当于集合)
查询区间
引自 岩之痕 大佬 >https://blog.csdn.net/zearot/article/details/52280189
查询区间的思想是将要询问的区间与现在处在的区间进行比较,我们模拟一下很容易知道,要查询的区间只有两种情况:我们那上图来做例子---1.查询2---4(包括在某个已经分好的节点(区间)中的--说白了就是被左或右区间包括的集合)---2.查询6---10(此区间与左和右区间有交集)--集合学得好的童鞋应该很容易理解
具体代码实现如下
void ask(int l,int r,int k) { if(tr[k].l>=l&&tr[k].r<=r) { ans+=tr[k].w; return; } if(tr[k].lazy) down(k); int mid=(tr[k].l+tr[k].r)/2; if(l<=mid) ask(l,r,k*2); if(r>mid) ask(l,r,k*2+1); //tr[k].w=tr[k*2].w+tr[k*2+1].w; }
好了,,查询和建树就先讲到这里,,下面的请看线段树基础知识--(基础数据结构)--二
标签:集合 时间 details -- 代码 为什么 问题 随机 算法思想
原文地址:https://www.cnblogs.com/liuyuhao040610/p/11234546.html