一天一道算法题——树状数组

题目【模板】树状数组1:https://www.luogu.com.cn/problem/P3374

树状数组和线段树差不多,可以处理区间操作,但是处理不了太复杂的区间问题。,不过代码比线段树简洁很多很多!!!时间复杂度都为O(logn)。

例如,区间[1,8]存储方式如下:

1 tree[1]=num[1];//001---001
2 tree[2]=num[2]+num[1];//010---010 001
3 tree[3]=num[3];//011---011
4 tree[4]=num[4]+num[3]+num[2]+num[1];//100---100 011 010 001
5 tree[5]=num[5];//101---101
6 tree[6]=num[6]+num[5];//110---110 101
7 tree[7]=num[7];//111---111
8 tree[8]=num[8]+num[7]+num[6]+num[5]+num[4]+num[3]+num[2]+num[1];///1000---1000 0111 0110 0101 0100 0011 0010 0001

从注释可以看出存储方式和二进制有关系。

递推可得,当第x个数加上k时,tree[x]要加k,然后tree[x+x只剩最低位的1]也要加上x,循环往复。

根据负数在计算机中用补码存储可得k & -k即为x只剩最低位的1。

如7&-7

7用二进制表示为111,-7补码形式为001,111&001得001,所以7只剩最低位的1为001.

AC代码:

#include<iostream>
#include<stdio.h>
#include<algorithm>
#define maxn 500010
typedef long long ll;
using namespace std;

int n;
ll tree[maxn << 2];

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

void add(int x, ll k) {
    while (x <= n) {
        tree[x] += k;
        x += lowbit(x);
    }
}
ll sum(int x) {
    ll ans = 0;
    while (x != 0) {
        ans += tree[x];
        x -= lowbit(x);
    }
    return ans;
}

int main() {
    int m, k, x, y;
    ll a;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &a);
        add(i,a);
    }
    while (m--) {
        cin >> k;
        if (k == 1) {
            scanf("%d%lld", &x, &a);
            add(x,a);
        }
        else {
            scanf("%d%d", &x, &y);
            if (x <= y)
                cout << sum(y)-sum(x-1)<< endl;
        }
    }
    return 0;
}

O(∩_∩)O哈哈~

原文地址:https://www.cnblogs.com/zyyz1126/p/12603354.html

时间: 2024-10-10 07:07:08

一天一道算法题——树状数组的相关文章

经典算法题每日演练——第十题 树状数组

原文:经典算法题每日演练--第十题 树状数组 有一种数据结构是神奇的,神秘的,它展现了位运算与数组结合的神奇魅力,太牛逼的,它就是树状数组,这种数据结构不是神人是发现不了的. 一:概序 假如我现在有个需求,就是要频繁的求数组的前n项和,并且存在着数组中某些数字的频繁修改,那么我们该如何实现这样的需求?当然大家可以往 真实项目上靠一靠. ① 传统方法:根据索引修改为O(1),但是求前n项和为O(n). ②空间换时间方法:我开一个数组sum[],sum[i]=a[1]+....+a[i],那么有点意

算法基础-树状数组

今天我们分享一下树状数组,前置知识-了解树的结构,知道什么是左右儿子,各个节点的名称,也就是有点基础吧.今天以一个实际问题引出树状数组吧,中查询l-r的区间.(以B站大佬的课件为例子,可以关注下,在最后放上链接) 如果是暴力的话,显然时间复杂度是接受不了的(o(n方)),为了解决这个问题,我们就要用一些高级的数据结构.就是我们今天介绍的树状数组. 首先看下树状数组是什么, 树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log

【BZOJ4785】[Zjoi2017]树状数组 树套树(二维线段树)

[BZOJ4785][Zjoi2017]树状数组 Description 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道基础的树状数组题.给出一个长度为 n 的数组 A,初始值都为 0,接下来进行 m 次操作,操作有两种: 1 x,表示将 Ax 变成 (Ax + 1) mod 2. 2 l r,表示询问 sigma(Ai) mod 2,L<=i<=r 尽管那个时候的可怜非常的 simple,但是她还是发现这题可以用树状数组做.当时非常yo

【bzoj4785】[Zjoi2017]树状数组 线段树套线段树

题目描述 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道基础的树状数组题.给出一个长度为 n 的数组 A,初始值都为 0,接下来进行 m 次操作,操作有两种: 1 x,表示将 Ax 变成 (Ax + 1) mod 2. 2 l r,表示询问 sigma(Ai) mod 2,L<=i<=r 尽管那个时候的可怜非常的 simple,但是她还是发现这题可以用树状数组做.当时非常young 的她写了如下的算法: 1: function Add(x

Zjoi2017树状数组

2.1 题目描述 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的 OI 比赛经历.那是一道基础的树状数组题. 给出一个长度为 n 的数组 A,初始值都为 0,接下来进行 m 次操作,操作有两种: ? 1 x,表示将 Ax 变成 (Ax + 1) mod 2. ? 2 l r,表示询问 ( ∑r i=l Ai) mod 2. 尽管那个时候的可怜非常的 simple,但是她还是发现这题可以用树状数组做. 当时非常 young 的她写了如下的算法: 1: functio

Poj(2352)——Stars(树状数组)

Description Astronomers often examine star maps where stars are represented by points on a plane and each star has Cartesian coordinates. Let the level of a star be an amount of the stars that are not higher and not to the right of the given star. As

bzoj4785【Zjoi2017】树状数组

漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的 OI 比赛经历.那是一道基础的树状数组题. 给出一个长度为 nn 的数组 AA,初始值都为 00,接下来进行 mm 次操作,操作有两种: 1 x1 x, 表示将 AxAx 变成 (Ax+1)mod2(Ax+1)mod2. 2 l r2 l r, 表示询问 (∑ri=lAi)mod2(∑i=lrAi)mod2. 尽管那个时候的可怜非常的 simple,但是她还是发现这题可以用树状数组做.当时非常 young 的她写了如

POJ2299题解(树状数组)

POJ2299题解 2019-12-28 Powered by Gauss 1.题目传送门:POJ2299 2.理解题意: 做题的时候,第一步也是最重要的就是理解题意.记住这句话. POJ2299是一道标准的树状数组模板题.题意大致如下: 快速排序是一种非常优秀的排序方式,其精华在于循环比较和swap函数的应用. 先给你一个数N,表示这组数据(没错,这题是多组数据)数的个数,之后的N行,每行一个数Ai 请你输出在快速排序过程中经历的swap函数的次数. 3.算法思路: 树状数组是一种非常高效的数

树状数组(二)与poj2155 - matrix

今天下午,我进行了树状数组的进一步学习[1],并完成了poj2155的编程与调试,下面是一些记录与感想. 这道题目是一道二维树状数组的练习,中心思想如下: 1.C(x1, y1)(x2, y2)可以用c[x1][y1]++.c[x2 + 1][y1]++.c[x1][y1 + 1]--.c[x2 + 1][y2 + 1]--进行记录(证明与推理过程在注释[1]中). 2.Q(x, y)利用二维树状数组对c[1][1]到c[x][y]的累加和%2(即mod 2)求得(请各位参看注释[1]的资料自行