zoukankan      html  css  js  c++  java
  • 线段树的总结

    恩推倒重写.

    线段树就是一棵二叉树,保存区间的左右值,查询时合并结果.这样可以吧线性复杂度转化为$O(log{n})$时间复杂度.

    线段树的构造很简单.

    struct node{
    	int left,right,data;
    	struct sign{
    		int type;
    	} sign;
    } nodes[200000];
    

    这保存了一个结点.data保存即时询问的东西.sign保存lazy-tags

    线段树的初始化即赋初始值.此时无需memset一遍

    int build_tree(int index,int left,int right){
    	nodes[index].left=left;
    	nodes[index].right=right;
    	nodes[index].sign.type=0;
    //初始值先生
    	if(left==right){
    		nodes[index].data=1;
    		hashTreeNode[left]=i;
    		return nodes[index].data;
    	}
    //如果是点,就没有子结点了.这时初始化
    	int mid=(left+right)/2,i2=index*2;
    //如果是线段
    	return nodes[index].data=build_tree(i2,left,mid)+build_tree(i2+1,mid+1,right);
    //就递归建树,将初始值相加
    }
    

    可以看出这里传递的指针是不会浮动的不会引喻失意[口胡状>引用到非树中结点

    int update(int i,int l,int r,int t){
    	int left,right,mid,tt;
    	left=nodes[i].left;
    	right=nodes[i].right;
    	if(l==left&&r==right){
    		addTag(i,t);//为i打标记
    	}
    	mid=left+right;
    	mid=mid/2;
    
    	if(hasTag(i)){//如果有标记
    		tt=getTag(i);//返回i标记的值
    		clearTag(i);//清除i的标记
    		update( i*2 , left, mid ,tt);
    		update(i*2+1,mid+1,right,tt);
    //将标记推到子结点,O(1) (刚好完全反应[口胡>恰好是子结点left和right)
    	}
    	if(l<=mid) update( i*2 ,     l      ,min(mid,r),t);//推到子结点进行递推
    	if(r >mid) update(i*2+1,max(l,mid+1),     r    ,t);//同理咯
    //被完全覆盖的结点总是不会递推到它的子结点的,所以保证了O(log n)因为每层访问两个结点
    	joinResult(i);
    //对i进行合并子结点的结果
    }
    //addTag,getTag,clearTag,joinResult均视实际情况自己实现
    

    query的实现

    query也是一大问题.一般来说可以通过和update类似的方法来处理.特殊情况可以用奇葩方法处理.

    int query(int t,int l,int r,int t){
    	int left,right,mid,tt=0;
    	left=nodes[i].left;
    	right=nodes[i].right;
    	pushdown(i);//pushdown就是将标记传递给子结点,清空自己的标记并将结果统计在data里
    	if(l==left&&r==right){
    		return i.data;
    	}
    	if(l<=mid) tt+=query( i*2 ,     l      ,min(mid,r),t);//统计出tt
    	if(r >mid) tt+=query(i*2+1,max(l,mid+1),     r    ,t);
    	return tt;
    }
    

    不保证正确...不过这就是我的总结了.重点在注释部分.

    恩特殊情况是----hdu1698

    这里由于统计是全局的,实现相当简单.

    int query(int t){
    	if(nodes[t].sign.type || nodes[t].left==nodes[t].right) return nodes[t].data;//再逗逼的OIer也能看得懂
    	return query(t*2)+query(t*2+1);
    }
    

    恩比如说我.


    恩语文渣渣,常口胡啥的.

  • 相关阅读:
    log4net的使用
    数据库概念及构成
    基于C#WPF框架——动画
    基于C# WPF框架的贪吃蛇
    使用Teigha.net读取CAD的常用功能模块
    Teigha.net实体属性注释
    .net(C#数据库访问) Mysql,Sql server,Sqlite,Access四种数据库的连接方式
    Delphi解析修改Json文件,基于superobject.pas(ISuperObject)
    C++结构体与Delphi结构体相互传参,结构体中包含结构体的嵌套,数组指针
    C++ Json解析CJsonObject的详细使用
  • 原文地址:https://www.cnblogs.com/tmzbot/p/4047098.html
Copyright © 2011-2022 走看看