zkw线段树 -1(单点更新 区间求和)

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<vector>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
#define inf 0x3f3f3f3f
#define lowb(x) x&-x
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define per(i,j,k) for(int i=j;i>=k;i--)
#define N 100005
#define esp 1e-6
int M;
int t[2*N];

void build(int n)
{
    for(M=1;M<n;M<<=1);//建树
    for(int i=1;i<=n;i++)
        scanf("%d",&t[M+i]);
    per(i,M-2,1) t[i]=t[i<<1]+t[i<<1|1]; 
}

int query(int L,int R)
{
    int ans=0;
    int l=M+L-1;
    int r=M+R+1;
    for(;l^r^1;l>>=1,r>>=1)
    {
        if(~l&1)ans+=t[l^1];
        if(r&1) ans+=t[r^1];
    }
    return ans;
}

void upd(int x,int k)
{
    t[x+M]+=k;
    x=(x+M)>>1;
    for(;x;x>>=1) t[x]=t[x<<1]+t[x<<1|1];
}

int main()
{
    int tt;
    cin>>tt;
    int cnt=0;
    while(tt--)
    {
        memset(t,0,sizeof(t));
        int n;
        scanf("%d",&n);
        build(n);
        char s[6];
        int i,j;
        printf("Case %d:\n",++cnt);
        while(~scanf("%s",s))
        {
            if(s[0]=='E')break;
            scanf("%d%d",&i,&j);
            if(s[0]=='A') upd(i,j);
            if(s[0]=='S') upd(i,-j);
            else if(s[0]=='Q')printf("%d\n",query(i,j));
        }
    }
}

 刚刚学习了zkw线段树,感觉代码量很小,尤其是建树操作,只需要两行,(其实递归版的线段树也没有几行),虽然我目前只是学习了基本的思想,但是我还是想把自己的理解记录下来,以供以后查看。

需要注意的点

1. zkw线段树一般情况下需要的空间是2*n,最坏的情况下是4*n-1,因为我们把元素都存在了最后一层

而最后一层可以存2的n-1次方(n代表层数)个元素,即使少一个也要多开*2的空间

比如最后一层我们能存1024个元素 但是我们有1025个元素,那么不好意思

我们只能将数组的空间再扩大2倍。

2.元素的下标是从M+1开始存的(M是最小的大于n的2的幂次方)之所以从m+1开始存与它的查询方式有关。

他的查询方式是开区间查询如果要查询[l,r],就转化成查询[l-1,r+1];

例如对于本图圆圈中的数字代表第几个元素,上方的数字代表在数组中的位置。

现在要查询1-6 转化为查询转化后[M+l-1,M+r+1] 即转化为了[8-15];

扫描二维码关注公众号,回复: 2525811 查看本文章

对于两个兄弟节点来说,如果一个节点为左儿子,那么另一个节点为右儿子

所以说对于左端点来说,如果他是左儿子那么他的兄弟节点一定包含在区间内

对于右端点来说,如果他是右节点那么他的兄弟节点一定包含在查询区间内。

由此左右分别从下往上查询,并且不会查询到交集。查询停止的条件就是左右

端点成为了兄弟节点,即L^R^1=0,因为如果L与R相差1那么L^R=1,1^1=0;

另外需要注意的点就是单点更新的时候t[x+M]+=k;之后当前点已经更新了

需要往上移动了x=(x+M)>>1; 刚开始忘了写这一句,一直不知道bug出哪里。。

瞌睡。。碎觉。

猜你喜欢

转载自blog.csdn.net/weixin_40894017/article/details/81229170