传送门
让我们先来一道特别简单的题目--单点修改与查询区间和
先贴一套PPT里面的图
上面就是zkw线段树的查询区间和方法...
当然,直接贴图当然很玄学...
分步来:
找到树的深度m[这里的深度定义为树的层数].ps:如果这个数不是满二叉树会自动将其添满0.
找出根到第一个叶子节点的距离,距离为.
然后将每个数字读入,数字在线段树中的下标为i+m.
建树,对于每一棵子树,它的根节点是两个儿子的节点之和.
查询:首先找到它的闭区间[s,t](原数组下标+m),然后将它改为开区间,随后s、t一路找爸爸,如果s是左儿子,则加上s的右兄弟,如果t是右儿子,则加上t的左兄弟,当s与t是兄弟时,则退出..
修改:先找到修改的叶节点x,将它修改,然后把x一路找爸爸,一路上遇到的所有点都修改.
大家可以和上面的图一起对照着看...
再不贴代码会不会打我...
//notes:根据zkw的《统计的力量》,做出来的四不像
#include <algorithm>
#include <bitset>
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <limits>
#include <list>
#include <map>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <utility>
#include <vector>
#include <cwchar>
#include <cwctype>
#include <complex.h>
#include <fenv.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
#include <tgmath.h>
#define F(i,a,b) for(int i=a;i<=b;i++)
#define D(i,a,b) for(int i=a;i>=b;i--)
#define MAXN 500050
#define LL long long
#define INF 0X3F3F3F3F
#define MINF 9999999999999999
using namespace std;
inline bool read(int &num)
{
char in;bool IsN=false;
in=getchar();
if(in==EOF) return false;
while(in!='-'&&(in<'0'||in>'9')) in=getchar();
if(in=='-'){ IsN=true;num=0;}
else num=in-'0';
while(in=getchar(),in>='0'&&in<='9')
{
num*=10,num+=in-'0';
}
if(IsN) num=-num;
return true;
}
//以上是优美的快读和头文件
int tree[4*MAXN],n,m;
int query(int s,int t )//询问s到t 的闭区间和[左右都取]
{
int res=0;
s=t-1,t=t+1;//将它变成开区间(左右都不取)
s+=m,t+=m;//m是该线段树的叶子层的元素个数.
while(~(s ^ t)/*s和t不是兄弟*/)
{
if(s&1) res+=tree[s^1];//判断s是否为左节点,若是,则加上右节点
if(~t&1) res+=tree[t^1];//判断t是否为右节点,若是,则加上左节点
s>>=1,t>>=1;//将它改为它的父节点
}
return res;
}
void change(int x,int val)
{
x+=m;//找叶子
tree[x]=val;//修改它本身
while(x>1)
{
x>>1;//找爸爸
tree[x]=tree[x<<1]+tree[x<<1^1];//修改爸爸..
}
}
void init()
{
read(n);
for(m=1;m<n+2;m<<=1);
//求出m
F(i,m+1,m+n)
{
read(tree[i]);
}//输入
D(i,m-1,1)
{
tree[i]=tree[2*i]+tree[2*i+1];
}//建树
}
没了...