线段树模板

 线段树基础入门

 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

posted @ 2017-09-27 21:23  浅忆~  阅读(137)  评论(0编辑  收藏  举报