7.28日结

昨天对树状数组的理解好像有点问题,今天又重新理解了一下,首先是这三个最基本的代码

int lowbit(int x){
    return x&(-x);
}
void add(int x,int k){
    for(;x<=n;x+=lowbit(x))
        t[x]+=k;
}
int ask(int x){
    int ans=0;
    for(;x;x-=lowbit(x))
        ans+=t[x];
    return ans;
}

场景1:单点修改,单点/区间查询。
单点x修改add( x , k ),单点x查询ask( x ) - ask( x-1),区间 [ l , r ] 查询ask( r ) - ask( l-1),
原数组就是 t [ x ] ,不难看出单点查询就是区间查询的子情况, t [ x ]表示子节点值之和,所以add 改变时也要算上父节点
例题

场景2:区间修改,单点查询。
区间 [ l , r ] 修改add( l , k ),add( r+1,-k ),单点x查询ask( x )
这个地方与上一个不同,原数组是 a [ x ], 差分数组 t [ x ]= a [ x ] - a [ x-1 ] + t [x ]子节点之和,输入a [ x ]后计算完 t [ x ]就不再对a [ x ]进行任何操作
在这里插入图片描述
这时候的的ask( x )也发生了改变,t 数组相加求的是修改后的 a [ x ]值,对于区间 [ l , r ] 改变 t [ l ] 和 t [ r+1 ],但不能仅改变 t [ l ] 和 t [ r+1 ], t [ l ] 改变时,也改变了他的父节点,单个改变和也改变,实际上只有 a [ l ] - a [ l-1 ] 和a [ r+1 ] - a [ r ] 改变了,a [ l+1 ] - a [ l ]到a [ r ] - a [ r-1 ] 是不变的
例题

场景3:区间修改,区间查询。
这个我认为比较特殊。先附上例题(虽然标签是线段树,但却是典型的区间修改+区间查询),再附上代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
long long t1[100010],t2[100010],a[100010];
int n,m;
int lowbit(int x){
    return x&(-x);
}
void add(int x,long long k){
    for(int i=x;i<=n;i+=lowbit(i))
    {
        t1[i]+=k;
        t2[i]+=x*k;
    }
}
long long ask(int x){
    long long ans=0;
    for(int i=x;i>0;i-=lowbit(i))
        ans+=(x+1)*t1[i]-t2[i];
    return ans;
}
int main()
{
	cin>>n>>m;
	a[0]=0;
	for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        add(i,a[i]-a[i-1]);
    }
	while(m--)
    {
        int s;
        scanf("%d",&s);
        if(s==1)
        {
            int x,y;
            long long k;
            scanf("%d %d %lld",&x,&y,&k);
            add(x,k);
            add(y+1,-k);
        }
        else
        {
            int x,y;
            scanf("%d %d",&x,&y);
            printf("%lld\n",ask(y)-ask(x-1));
        }
    }
	return 0;
}

首先是和场景2一样的差分数组,该题设为 t 1

 a[1]+a[2]+……+a[r-1]+a[r]
=t1[1]+(t1[1]+t1[2])+……+(t1[1]+……+t1[r])
=(t1[1]*(r))+(t1[2]*(r-1))+……(t1[r]*1)
=r*(t1[1]+t1[2]+……+t1[r])-(t1[1]*0+t1[2]*1+……+t1[r]*(r-1))
=(r+1)*(t1[1]+t1[2]+……+t1[r])-(t1[1]*1+t1[2]*2+……+t1[r]*r)

对于 (t1[1]*1+t1[2]*2+……+t1[r]*r) *这一部分,用 t1 的求和比较难写,所以设另一个数组 t 2 ,使得 t 2 [ i ] = t 1 [ i ] * i,并且保证和 t 1 同时更新,这里我的更新 add 是把两个同时在一起写的(因为懒),一个要注意的点是:代码中 add 的 x 是恒定不变的,所以不能像 / 场景2那样不设 i 直接直接对 x 进行改变/,因此我用 i 来作为循环的数,就在这个地方我犯了一个低级的错误把 i >0;(或直接 i; 也可以)写成了 i >=0找了好久才找到,写下来提醒一下自己

回顾一下这两天,感觉第一天只搞懂了原理,第二天才开始看应用做了基础的几个题,确实效率有点低。

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 、 1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READmE.文件(md如有),本项目仅用作交流学习参考,请切勿用于商业用途。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值