• 线段树模板


     线段树基础入门

     1 #include <stdio.h>
     2 #include <math.h>
     3 const int maxnode=287...
     4 const int maxn=10000003;
     5 struct{
     6     int value;  //结点对应区间的权值
     7     int left,right;  //区间[left,right]
     8 }node[maxnode];
     9 int father[maxn];   //每个点(当区间长度为0时,对应一个点)对应的结构体数组下标
    10 
    11 ft==right){ //当区间长度为0时,结束递归
    12         fathevoid BuildTree(int i,int left,int right){ //为区间[left,right]建立一个以i为祖先的线段树,i为数组下标,即结点序号
    13     node[i].left=left;  //写入第i个结点中的左区间
    14     node[i].right=right;//写入第i个结点中的右区间
    15     node[i].value=0;  //每个区间初始化为0
    16     if(left==right){ //当区间长度为0时,结束递归
    17     father[left]=i;//能知道某个点对应的序号,为了更新的时候从下往上一直到顶
    18     return ;
    19     }
    20     //该结点往 左孩子的方向 继续建立线段树,线段的划分是二分思想
    21     //这里将 区间(left,right)一分为二啦
    22     BuildTree(i<<1,left,(int)floor((right+left)/2.0));
    23     //该结点往 右孩子的方向 继续建立线段树
    24     BuildTree((i<<1)+1,(int)floor((right+left)/2.0)+1,right);
    25 }
    26 /*
    27 由于事先用father[]数组保存过每单个结点对应的下标了,因此只需要知道第几个点,就能知道这个点在结构体中的位置关系
    28 
    29  */
    30 void UpdateTree(int ri){  //从下往上更新(注;这个点本身已经在函数外更新过啦)
    31     if(ri==1) return;  //向上已经找到了祖先(整个线段树的祖先结点 对应的下标为1)
    32     int fi=ri/2;//ri的父结点
    33     int a=node[fi<<1].value;//该父结点的两个孩子结点(左)
    34     int b=node[(fi<<1)+1].value;//
    35     node[fi].value=(a>b)?(a):(b);//更新这个父结点(从两个孩子结点中挑个最大的))
    36     UpdateTree(ri/2);  //递归更新,由父结点往上找
    37 }
     1 /*
     2  将一段区间按照建立的线段树从上往下一直拆开,直到存在有完全重合的区间停止。
     3  
     4  */
     5 int Max=-1<<20;  //很小很小
     6 void Query(int i,int l,int r){
     7     if(node[i].left==l&&node[i].right==r){
     8     Max=(Max<node[i].value)?node[i].value:(Max);
     9     return ;
    10     }
    11     i=i<<1;  //get the left child of the tree node
    12     if(i<node[i].right){  //左区间有涉及
    13         if(r<=node[i].right) //全包含于左区间,则查询区间形态不变
    14           Query(i,l,r);   //半包含于左区间,则查询区间拆分,左端点不变,右端点变
    15 为左孩子的右区间端点
    16         else Query(i,l,node[i].right);
    17     }
    18     i+=1;  //right child of the tree
    19     if(r>=node[i].left){  //右区间有涉及
    20         if(l>=node[i].left){  //全包含于右区间,则查询区间形态不变
    21             Query(i,l,r);
    22             else //半包含于左区间,则查询区间拆分,与上同理
    23                 Query(i,node[i].left,r);
    24         }
    25     }
    26 }

     https://www.2cto.com/kf/201608/532990.html

    线段树之延迟标记(区间修改)

    /*
     延迟标记(lazy Tag)
     延迟标记作用于递归过程中,如果当前区间被需要修改的目标区间完全覆盖,那么就可停>
    止递归,做一个延迟标记,但是这个信息没有更新到其下每个元素(即到叶子节点),下次
    查询的时候可能无法得到足够的信息,这时就需要延迟标记啦,它不仅是这个节点的性质,
    还作用于整个子树中。如果我们另一个查询中包含了当前区间的子区间,那么这个标记就分
    解,传递给其左右儿子。
     简单地说,延迟标记在需要时,才向下传递更新信息,如果没有用到,则“沉睡”,复杂度O
    (log2(n))。
     为了完成这种操作,我们可以在结构体中,增加一个add数组存储区间的延迟变化量
     
     */ 

    poj

  • 相关阅读:
    如何查看IIS的80端口被占用? 拂晓风起
    配置VSS2005(在局域网内搭建服务器) 拂晓风起
    Log4Net ,.net和SQL Server的完美结合 拂晓风起
    SQL Server简单使用配置 拂晓风起
    ztree图标不显示
    oracle添加同义词
    Struts2作用域和标签库(转)
    java实现链表(转)
    unexpected end of subtree(hql拼写有误,仔细查看hql语句,以及参数值的导入)
    http://www.mianwww.com/html/2012/10/17027.html面试题(经典)
  • 原文地址:https://www.cnblogs.com/z-712/p/7463943.html
Copyright © 2020-2023  润新知