一维树状数组模板【pascal】

本文详细介绍了树状数组的两种应用场景:单点修改区间查询及区间修改单点查询,并提供了Pascal与C语言实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、单点修改,区间查询

 

Pascal:

var
        n,m,tt,x,y      :longint;
        c               :array[0..500010] of longint;
        i               :longint;
function lowbit(x:longint):longint;
begin
   exit(x and (-x));
end;

procedure add(x,v:longint);
begin
   while (x<=n) do
   begin
      inc(c[x],v);
      inc(x,lowbit(x));
   end;
end;

function sum(x:longint):longint;
var
        ans:longint;
begin
   ans:=0;
   while (x>0) do
   begin
      inc(ans,c[x]);
      dec(x,lowbit(x));
   end;
   exit(ans);
end;

begin
   read(n,m);
   for i:=1 to n do
   begin
      read(x);
      add(i,x);
   end;
   //
   for i:=1 to m do
   begin
      read(tt,x,y);
      if (tt=1) then add(x,y) else writeln(sum(y)-sum(x-1));
   end;
end.

 

C(洛谷 P3374):

#include<stdio.h>

int n;
int c[500010];

int lowbit(int x) {
    return(x & -x);
}

void add(int x, int v) {
    while (x <= n) {
        c[x] += v;
        x += lowbit(x);
    }
}

int get_sum(int x){
    int ans = 0;
    while (x > 0) {
        ans += c[x];
        x -= lowbit(x);
    }
    return(ans);
}

int main(){
    int m;
    int i;
    int t, x, y;

    scanf("%d %d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%d", &x);
        add(i, x);
    }
    for (i = 1; i <= m; i++){
        scanf("%d %d %d", &t, &x, &y);
        if (t == 1) add(x, y); else printf("%d\n", get_sum(y) - get_sum(x - 1));
    }
}

 

 

2、区间修改,单点查询

引入差分数组d,设原数组为a,令d[i]=a[i]-a[i-1].由此关系式得,也就是a[j]等于d[j]的前 j 项和,即前缀和。

于此,我们的树状数组维护的是 d 的前缀和。

 

1、单点查询:

有以上推理得,查询a[i]相当于查询d[i]的前缀和,用树状数组操作即可(树状数组维护的是d数组)

 

2、区间修改:

因为对a的区间[i,j]加x,就相当于a[i]比a[i-1]大x,a[j+1]比a[j]小x,就相当于对a[i]加x,对a[j+1]减x。

因为a[i]等于d[i]的前缀和,所以a[i]+x就相当于对d[i]的前缀和加x,可以用树状数组操作。

同理,a[j+1]-x等于b[j+1]的前缀和减x,用树状数组操作

 

pascal:

 

var
        n,m,tt,x,y,z    :longint;
        c,a             :array[0..500010] of longint;
        i,j             :longint;
function lowbit(x:longint):longint;
begin
   exit(x and (-x));
end;

procedure add(x,v:longint);
begin
   while (x<=n) do
   begin
      inc(c[x],v);
      inc(x,lowbit(x));
   end;
end;

function sum(x:longint):longint;
var
        ans:longint;
begin
   ans:=0;
   while (x>0) do
   begin
      inc(ans,c[x]);
      dec(x,lowbit(x));
   end;
   exit(ans);
end;

begin
   read(n,m);
   for i:=1 to n do read(a[i]);
   for i:=1 to n do add(i,a[i]-a[i-1]); //注意
   //
   for i:=1 to m do
   begin
      read(tt);
      if (tt=1) then
      begin
         read(x,y,z);
         add(x,z);
         add(y+1,-z);
      end else
      begin
         read(x);
         writeln(sum(x));
      end;
   end;
end.

C(洛谷P3368):

#include<stdio.h>

int a[500010], c[500010];
int n;

int lowbit(int x) {
    return(x & -x);
}

void add(int x, int p) {
    while (x <= n) {
        c[x] += p;
        x += lowbit(x);
    }
}

int get_a(int x) {
    int ans = 0;

    while (x > 0) {
        ans += c[x];
        x -= lowbit(x);
    }
    return(ans);
}

int main () {
    int m;
    int i;
    int x, t, l, r;

    scanf("%d %d", &n, &m);
    a[0] = 0;

    for (i = 1; i <= n; i++) scanf("%d", &a[i]);
    for (i = 1; i <= n; i++) add(i, a[i] - a[i-1]);
    //
    for (i = 1; i <= m; i++) {
        scanf("%d", &t);
        if (t == 2) {
            scanf("%d" ,&x);
            printf("%d\n", get_a(x));
        } else {
            scanf("%d %d %d", &l, &r, &x);
            add(l, x);
            add(r + 1, -x);
        }
    }
    return 0;
}

 

 

——by Eirlys

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值