树状数组

log(n)修改,log(n)查询

可以顶替掉一部分线段树的作用,而且码量十分友好

但是对我来说是有点难理解的,现在只是大体理解,没有很通透,所以不写自己的理解了,以后要多看看

1.单点修改区间查询

https://blog.csdn.net/ls2868916989/article/details/119268741

代码(P3374):

#include<iostream>
#include<cstdio>
using namespace std;
const long long N=1e6+10;
int n,m,u,v,w,a[N];
int c[N];
int lowbit(int x){
    return x&(-x);
}
void change(int x,int y){
    while(x<=n){
        c[x]+=y;
        x+=lowbit(x);
    }
}
int print(int x){
    int cnt=0;
    while(x>0){
        cnt+=c[x];
        x-=lowbit(x);
    }
    return cnt;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=n;i++){
        int h=i;
        while(h<=n){
            c[h]+=a[i];
            h+=lowbit(h);
        }
    }
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&u,&v,&w);
        if(u==1) change(v,w);
        else printf("%d\n",print(w)-print(v-1));
    }
    return 0;
}

2.区间修改单点查询

去看这篇博客!!写的超级无敌好  https://www.cnblogs.com/daybreaking/p/9408301.html

大概的意思就是搞一个差分数组,修改的时候直接头尾一加一减,单点查询的时候要逐个相加

代码(P3374):

#include<iostream>
#include<cstdio>
using namespace std;
const long long N=1e6+10;
int n,m,a[N],d[N];
int c[N],k,u,v,w;
int lowbit(int x){
    return x&(-x);
}
void change(int x,int y){
    while(x<=n){
        c[x]+=y;
        x+=lowbit(x);
    }
}
int print(int x){
    int cnt=0;
    while(x>0){
        cnt+=c[x];
        x-=lowbit(x);
    }
    return cnt;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        d[i]=a[i]-a[i-1];
    }
    for(int i=1;i<=n;i++){
        int h=i;
        while(h<=n){
            c[h]+=d[i];
            h+=lowbit(h);
        }
    }
    for(int i=1;i<=m;i++){
        scanf("%d",&k);
        if(k==1){
            scanf("%d%d%d",&u,&v,&w);
            change(u,w);
            change(v+1,-w);
        }
        else{
            scanf("%d",&u);
            printf("%d\n",print(u));
        }
    }
    return 0;
}

 

posted @ 2023-08-03 13:39  dgdger  阅读(7)  评论(0编辑  收藏  举报