Live2D

线段树总介绍

如在阅读本文时遇到不懂的部分,请在评论区询问

 

1. 线段树是一种基于二叉搜索树的高级数据结构。它可以维护区间,包括求和、最值、某数个数、逆序对、区间合并.......

2. 线段树不仅仅是一种工具,更是一种思想方法。  -- Ryougi Kukoc

3. 下面介绍线段树的基♂操(我写线段树大括号是否换行,用结构体还是数组都很随意...)

//变量
int a[]; //原序列
int sum[],Max[],Min[],pre[],suf[],Maxistr[];
//维护区间: 和、最值、前驱、后继、最大子段和等等
int tag[]; //pt[],mt[],at[];加法、乘法、区间替换tag
#define LS (rt<<1)
#define RS (LS|1)

以下代码仅讲解区间加减、区间求和操作,其它特殊的维护参见 线段树目录 内的对应题解

建树

void build(int rt,int l,int r){
  //节点编号,左端点,右端点
    if(l==r){
      sum[rt]=a[l];return;
    }
    int mid=l+r>>1;
    build(LS,l,mid);
    build(RS,mid+1,r);
    pushup(rt); return;
}

 

区间修改

 

void update(int rt,int l,int r,int x,int y,int k){
    if(l>=x&&r<=y){
        sum[rt]+=(r-l+1)*k;
        tag[rt]+=k;
        return;
    }
   if(tag[rt])pushdown(rt,l,r); 
      int mid=l+r>>1;
  if(x<=mid)update(LS,l,mid,x,y,k); 
  if(y>mid)update(RS,mid+1,r,x,y,k); 
  pushup(rt); 
}

 

 

 

区间求和

 

int query(int rt,int l,int r,int x,int y){
    if(l>=x&&r<=y) return sum[rt];
    if(tag[rt])pushdown(rt,l,r)
    int mid=l+r>>1,res=0;
    if(x<=mid)res+=query(LS,l,mid,x,y);
    if(y>mid)res+=query(RS,mid+1,r,x,y);
    return res;
}

 

 

 

 pushdown和pushup

 

void pushdown(int rt,int l,int r){
    //if(!tag[rt])return;
    tag[LS]+=tag[rt];
    tag[RS]+=tag[rt];
    int mid=l+r>>1;
   sum[LS]+=tag[rt]*(mid-l+1);
    sum[RS]+=tag[rt]*(r-mid);
    tag[rt]=0;
    return ;
}
void pushup(int rt){
    sum[rt]=sum[LS]+sum[RS];
}

 

操作介绍完毕。

End

posted @ 2019-07-22 18:32  lsy263  阅读(239)  评论(0编辑  收藏  举报