zkw线段树

zkw线段树

1.来源 zkw统计的力量

醍醐灌顶啊

 

zkw线段树是一颗满二叉树

                   001

           010           011

    100     101    110    111

 

也许有助于理解一些位运算

 

一.建树

for(M=1;M<=n;M<<=1);
for(int i=1;i<=n;i++){
    a[i]=number();tr[M+i]=a[i];
}

M为叶子个数,前n层共M-1个点 

M保证最后一层要有>n个点

注意,叶子节点的第一个不放东西(也就是tr[M])

 

二.维护

for(int i=M-1;i;i--)tr[i]=tr[i<<1]+tr[i<<1|1];

三.单点查询

return tree[M+i]

四.区间查询

这很有意思

比如说查询[s,t]

转换为开区间(s,t)

那么显然s的右节点,t的左节点是有用的

于是

for(int s=l[i]+M-1,t=r[i]+M+1;s^t^1;s>>=1,t>>=1){
    if(~s&1)ans=max(aa,tr[s^1]);
    if(t&1)ans=max(aa,tr[t^1]);
}

补充:~为按位取反

也就是如果s为左子树 就将他的右子树加进答案

也就是如果t为右子树 就将他的左子树加进答案

s^t^1意思是s,t为同一棵子树的左右节点

 

五.单点更新

void change(int k,int v){
    tree[k+M]=v;
    for(int i=k+M;i;i>>=1)tree[i]=tree[i<<1]+tree[i<<1|1];
}

六.区间更新

差分思想

posted @ 2018-10-19 16:34  liankewei123456  阅读(136)  评论(0编辑  收藏  举报