线段树
- 会用到的公式:将完全二叉树从左到右、从上到下依次编号,设当前结点编号为n
- 左节点编号为:2*n 右节点编号为2*n+1
- 把空节点的编号初始化为-1
- 线段树的本质其实是二叉搜索树啦,所以说可以很方便的解决区间最大最小、查询区间和、修改区间和的问题
- 用数组表示线段树的话,如果本身的区间长度为n,线段树节点数2*n左右,开3*n的大小很保险
- 设线段树上节点代表区间为[a,b],那么左子树代表[a,(a+b)/2],右子树代表[(a+b)/2,b]
- 如果a==b,那么该节点为叶子结点,否则递归建树
先写了个很难看的代码…(并不能作为模板,模板在后面)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define maxn 50010
#define REP(a,b) for(int i=a;i<=b;i++)
using namespace std;
struct node{
int left,right,val;
}tree[maxn*3];
int s[maxn];
int ans=0;
void create(int l, int r, int num){
tree[num].left=l;
tree[num].right=r;
if(l==r) {
tree[num].val=s[l]; return;
}
else {
create(l,(l+r)/2,num*2);
create((l+r)/2+