//在我的理解里线段树并不是数据结构上所谓的树,而是通过数组模拟,通过
//函数进行下标转换(查询)
#include<algorithm>
#define maxn
using namespace std;
struct list
{
int left;
int right;
int _max;
int weight; //区间
}tree[maxn*4]; //乘4可以保证不会越界
//pushup 向上更新节点信息
//将左右子树的最大值放入父节点
void pushup(int id)
{
tree[id]._max=max(tree[id<<1]._max,tree[id<<1|1]._max);
}
//建树
void build(int i,int left,int right)
{
tree[i].left=left;
tree[i].right=right;
tree[i]._max=0;
if(left==right)
{
tree[i]._max=an[left]; //an数组应该是记录原始数据
return ;
}
int mid=(left+right)>>1;
build(i<<1,left,mid);
build(i<<1|1,mid+1,right);
pushup(i); //子节点更新完毕后,更新父节点
}
// 点查询
int ans=0; //查询结果
void query(int i,int pos)
{
if(pos==tree[i].left&&pos==tree[i].right)
{
ans=tree[i]._max;
return ;
}
int mid=(left+right)>>1;
if(pos<=mid)
query(i<<1,pos);
else
query(i<<1|1,pos);
}
//点更新
void update(int i,int data,int pos,int left,int right)
{
if(left==right)
{
tree[i]._max+=data;
return ;
}
int mid=(left+right)>>1;
if(pos<=mid)
update(i<<1,data,pos,left,mid);
else
update(i<<1|1,data,pos,mid+1,right);
pushup(i);
}
//向下更新
void pushdown(int i,int left,int right)
{
if(tree[i].weight) //懒惰标记
{
tree[i<<1].weight+=tree[i].weight;
tree[i<<1|1].weight+=tree[i].weight;
int mid=(left+right)>>1; //int m=l+((r-l)>>1);
tree[i<<1]._max+=tree[i].weight*(mid-left+1);
tree[i<<1|1]._max+=tree[i].weight*(right-mid);
tree[i].weight=0; //撤销标记
}
}
//区间更新
void update(int i,int ql,int qr,int data,int left,int right)
{
if(ql<=left&&qr>=right)
{
tree[i].weight+=data;
tree[i]._max+=data*(right-left+1);
return ;
}
pushdown(i,left,right);
int mid=(left+right)>>1;
if(ql<=mid)
update(i<<1,ql,qr,data,left,mid);
if(qr>=mid+1)
update(i<<1|1,ql,qr,data,mid+1,right);
pushup(i);
}
//区间查询
int ans=0;
void query(int i,int ql,int qr,int left,int right)
{
if(ql<=left&&qr>=right)
{
ans+=tree[i]._max
return ;
}
pushdown(i,left,right);
int mid=(left+right)>>1;
if(ql<=mid)
query(i<<1,ql,qr,left,mid);
if(qr>=mid+1)
query(i<<1|1,ql,qr,mid+1,right);
}
相关博客: