zoukankan      html  css  js  c++  java
  • 线段树 动态开点

    在一些计数问题中,线段树用于维护值域(一段权值范围),这样的线段树也称为权值线段树。为了降低空间复杂度,我们可以不建出整棵线段树的结构,而是在最初只建立一个根节点,代表整个区间,当需要访问线段树的某棵子树(某个子区间)时,再建立代表这个子区间的节点。采用这种方法维护的线段树称为动态开点的线段树。动态开点的线段树抛弃了完全二叉树父节点的2倍编号规则,改为使用变量记录左右子节点的编号(相当于指针)。同时,它也不再保存每个节点代表的区间,而是在每次递归访问的过程中作为参数传递。下面是一个动态开点的线段树的节点结构。

    struct segment_tree{
    	int lc,rc;   //左右子节点的编号
    	int dat;     //区间最大值
    }tree[maxn<<2];
    int root,tot;
    inline int build(){  //新建一个节点
    	tot++;
    	tree[tot].lc = tree[tot].rc = tree[tot].dat = 0;
    }
    int main(){
    	tot = 0;
    	root = build();  //根节点 
    }
    

      下面的代码对线段树单点修改的过程稍加变动,实现了在动态开点的线段树中把val位置上的值加delta,同时维护区间最大值的操作

    inline void update(int p,int l,int r,int val,int delta){
    	if(l == r){
    		tree[p].dat += delta;
    		return;
    	}
    	int mid = (l+r)>>1;  //代表的区间[l,r] 作为递归参数传递
    	if(val <= mid){
    		if(!tree[p].lc)tree[p].lc = build();
    		update(tree[p].lc,l,mid,val,delta);
    	}
    	else{
    		if(!tree[p].rc)tree[p].rc = build();  //动态开点
    		update(tree[p].rc,mid+1,r,val,delta);
    	}
    	tree[p].dat = max(tree[tree[p].lc].dat,tree[tree[p].rc].dat);
    }
    

      

  • 相关阅读:
    Linux用户、用户组、文件权限设置
    spring,springMvc和mybatis整合配置
    spring,springMvc和hibernate整合
    spring与mybatis
    spring与Dbcp
    初识事物
    spring与Aop
    初识spring
    mysql 完整性约束
    mysql数据库的基本操作
  • 原文地址:https://www.cnblogs.com/wangyifan124/p/10306840.html
Copyright © 2011-2022 走看看