线段树

来源:互联网 发布:手机内窥镜软件 编辑:程序博客网 时间:2024/06/11 19:40

结合之前遇到的题目,线段树的题目共可以分为

1、单点更新,这类题目一般简单的理解变形后可以直接参照模板解题。

2、区间更新,区间更新的题目。

3、lazy标记,使用lazy标记的目的在于时数据的处理过程简化,使得运行时间得到优化,使用方法是只要区间完全包含在要操作的区间中就把这个点的值进行维护,在以后对某一点的操作时直接进行维护书的相加。

4、扫描线,常用来解决组合图形求面积的问题。



二维线段树模板

#include<iostream>   

#include<cstdio> 

#include<cstring> 

#include<algorithm>

using namespace std;

const int N=;

int tree[N][N<<2];

//建立y轴方向上的线段树,作为一维线段树的一个节点

void Build_2(int node,int left,intright,int deep){

   tree[deep][rt]=-1.0;

   if(left==right) return ;

   int mid=(left+right)>>1;

   Build_2(node<<1,left,mid,deep);

   Build_2(node<<1|1,mid+1,right,deep);

}

//建立x轴方向上的线段树,正常的一维建树,不同于一维线段树的地方在,二维线段树的一位表示是一个一维线段树

void Build(int node,int left,int right){

   Build_2(1,/*区间左端点*/,/*区间右端点*/,node);

   if(left==right) return;

   int mid=(left+right)>>1;

   Build(node<<1,left,mid);

   Build(node<<1|1,mid+1,right);

}

//对二维线段树(y轴)的信息做更新操作

void Update_2(int node,int left,intright,int deep,int value){

   if(left==right) {/*更新操作*/return ;}

   int mid=(left+right)>>1;

   if(value<=mid) Update_2(node<<1,left,mid,deep,value);

   else Update_2(node<<1|1,mid+1,right,deep,value);

   tree[deep][node]=max(tree[deep][node<<1],tree[deep][node<<1|1]);

}

//对一维线段树(x轴)信息做更新操作

void Update(int node,int left,int right,intvalue1,int value2){

  if(left==right) {Update_2(1,/*区间左端点*/,/*区间右端点*/,node,value2);return ;}

  int mid=(left+right)>>1;

  if(value1<=mid) Update(node<<1,left,mid,value1,value2);

  else Update(node<<1|1,mid+1,right,value1,value2);

}

//二维线段树查询操作

int Query_2(int node,int left,int right,intdeep,int Qleft,int Qright){

   if(Qleft>=left&&Qright<=right) return tree[deep][node];

   int mid=(left+right)>>1;

   if(Qright<=mid) returnQuery_2(node<<1,left,mid,deep,Qleft,Qright);

   else if(Qleft>mid) returnQuery_2(node<<1|1,mid+1,right,deep,Qleft,Qright);

   else returnmax(Query_2(node<<1,left,mid,deep,Qleft,Qright),Query_2(node<<1|1,mid+1,right,deep,Qleft,Qright));

}

//一维线段树查询操作

int Query(int node,int left,int right,intQ1,int Q2,int V1,int V2){

   if(Q1>=left&&Q2<=right) return Query_2(1,/**/,/**/,node,V1,V2);

   int mid=(left+right)>>1;

   if(Q2<=mid) return Query(node<<1,left,mid,Q1,Q2,V1,V2);

   else if(Q1>mid) returnQuery(node<<1|1,mid+1,right,Q1,Q2,V1,V2);

   elsemax(Query(node<<1,left,mid,Q1,Q2,V1,V2),Query(node<<1|1,mid+1,right,Q1,Q2,V1,V2));

}

int main(){

   /*题目具体实现*/

}





个人对于二维线段树的认识,在需要两个变量区间维护一个值是用到二维线段树,和一维线段树不同的地方在于,二维线段树可以看成是节点为一个线段树的一维线段树。目前接触的线段树的题目基本是模板题,所以明白代码的写法还是比较重要的,教练说过现在这个阶段还是需要扎实基础,基础打得牢以后的的创新题才会比较好做。

原创粉丝点击