zkw线段树

ZKW线段树


杂说


    最近老是被数据结构血虐,目前就学了 字典树,树状数组,准备学线段树,看到网上一直在推广zkw线段树。所以决定学这个。
    zkw线段树优点有很多,常数小,好写,等等。不再叙述(因为我也不懂)
    总的来说,就我个人理解,zkw线段树总共分两种,一种就是普通维护:需要什么维护什么,比如维护区间和,维护区间最大值、最小值等等。另一种就是差分维护:节点存储与父节点(一开始父节点为两个子节点的最小值)的差值。

普通维护

    首先是建树

建树

    建树自然是要先预分配空间,我的分配方法是先算出位数,比如他有1-n的区间需要维护,那么先求出 int(logn2) i n t ( log 2 n ) +2,然后

const int N=1<<k;//k就是上面的值,先预先求好
int d[N];
int M;

    空间分配好之后就建树

void build(int n){
    for(M=1;M<n;M<<=1);
//M是叶子节点开始储存的位置
    for(int i=M+1;i<=M+n;i++)
        scanf("%d",&d[i]);
    //以上在建立叶子节点
    for(int i=M-1;i;i--)
        //d[i]=min(d[i<<1],d[i<<1|1]);
        //这样子算是维护最小值    
        d[i]=d[i<<1]+d[i<<1|1];//维护和     
   //以上在建立父节点
}

     建树代码很简单就完成

维护

单点修改

x是元素位置,v是元素增量

void Change(int x,int v){
    d[x=M+x]+=v;
    while(x) d[x>>=1]=d[x<<1]+d[x<<1|1];
}



区间修改

还不会。


查询


区间和查询

int Sum(int s,int t,int Ans=0){
        for (s=s+M-1,t=t+M+1;s^t^1;s>>=1,t>>=1){//先变开区间
              if(~s&1) Ans+=d[s^1];//&1判断是不是右子树,^1另一个子树
              if( t&1) Ans+=d[t^1];
        }
        return Ans;
}


区间和查询

int Min(int s,int t,int ans=999999){
        for (s=s+M-1,t=t+M+1;s^t^1;s>>=1,t>>=1){//先变开区间
              if(~s&1) ans=min(ans,d[s^1]);//&1判断是不是右子树,^1另一个子树
              if( t&1) ans=min(ans,d[t^1]);
        }
        return ans;
}

未完待续,正在学习


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值