PJ蒟蒻的zkw线段树详解(2)--单点修改_查询区间和

传送门

让我们先来一道特别简单的题目--单点修改与查询区间和

先贴一套PPT里面的图

PJ蒟蒻的zkw线段树详解(2)--单点修改_查询区间和_第1张图片

 

PJ蒟蒻的zkw线段树详解(2)--单点修改_查询区间和_第2张图片

上面就是zkw线段树的查询区间和方法...

当然,直接贴图当然很玄学...

分步来:

  1. 找到树的深度m[这里的深度定义为树的层数].ps:如果这个数不是满二叉树会自动将其添满0.

  2. 找出根到第一个叶子节点的距离,距离为2^{m}.

  3. 然后将每个数字读入,数字在线段树中的下标为i+m.

  4. 建树,对于每一棵子树,它的根节点是两个儿子的节点之和.

  5. 查询:首先找到它的闭区间[s,t](原数组下标+m),然后将它改为开区间,随后s、t一路找爸爸,如果s是左儿子,则加上s的右兄弟,如果t是右儿子,则加上t的左兄弟,当s与t是兄弟时,则退出..

  6. 修改:先找到修改的叶节点x,将它修改,然后把x一路找爸爸,一路上遇到的所有点都修改.

大家可以和上面的图一起对照着看...

再不贴代码会不会打我...

//notes:根据zkw的《统计的力量》,做出来的四不像 
#include    
#include      
#include 
#include 
#include 
#include 
#include     
#include 
#include 
#include 
#include 
#include      
#include     
#include 
#include    
#include 
#include       
#include        
#include 
#include        
#include      
#include 
#include     
#include    
#include     
#include     
#include   
#include       
#include    
#include   
#include      
#include     
#include    
#include 
#include 
#include   
#include     
#include   
#include  
#include   
#include    
#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

没了...

留下你的赞!

你可能感兴趣的:(zkw线段树)