树状数组学习(一维)

算法描述

可以对给定序列进行查询和修改

查询:主要用来查询任意两位之间数据和

修改:修改单项数据值

时间复杂度:log(n)

算法思想

1.数组的构建

定义 数组C A

C1 = A1

C2 = A1 + A2

C3 = A3

C4 = A1 + A2 + A3 + A4

C5 = A5

C6 = A5 + A6

C7 = A7

C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8

不难看出,其实是实现了对A的数据的分别管辖,Cn的管辖数量为 将n化为二进制数后,末尾连续零的数量; 也可这样理解,令 2^k <=n ; 则 k 的最大值即为管辖数量

这里介绍一种求2^k的方法,后面会用到

int lowbit(int x)
{
    return x&(-x); //运用位运算及机器补码
}

调用 lowbit(n) , 即可得出Cn的管辖数量

而Cn的管辖范围为 : n-lowbit(n)+1 到 n

void make_tree(int n)
{
    for(int i=1;i<=n;i++)
    {
        for(int j=i-lowbit(i)+1;j<=i;j++)
        {
            c[i]+=a[j];
        }
    }
}

2.求和

令sum=0;

遍历,每次将n的二进制数最后一位1 化为 0 ,依次 sum += C[n],n=n-lowbit(n),直到n<=0;

sum值即为序列 1 ~ n 的总和

int make_sum(int n)
{
    int sum=0;
    while(n>0)
    {
        sum+=c[n];
        n-=lowbit(n);
    }
    return sum;
}

3.修改单项数据

对每个包含Ai 的 Cn进行修改

void modify(int n,int i,int num)
{
    while(i<=n)
    {
        c[i]+=num-a[i];
        i+=lowbit(i);
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-29 21:21:11

树状数组学习(一维)的相关文章

树状数组学习资料1

1 一维树状数组 1 什么是树状数组 树状数组是一个查询和修改复杂度都为log(n)的数据结构,假设数组A[1..n],那么查询A[1]+...+A[n]的时,间是log级别的,而且是一个在线的数据结构. 2 树状数组作用 我们经常会遇到动态连续和查询问题,给定n个元素A[1~N],让我们求sum[L,R] = A[L]+...+A[R],或者更改A[i]的值. 假设数据很小的时候,那么我们利用暴力就可以搞定,这个时候更改A[i]的复杂度为O(1),但是求和的复杂度为O(n),如果有m次求和就是

资瓷区间修改+区间求和的树状数组(一维/二维)

一维:令 \(v_i\) 为差分数组,那么 \([0, k]\) 的前缀和就是 \(\sum{v_i(k+1-i)} = (k+1) \cdot \sum{v_i} + \sum{v_i \cdot (-i)}\),树状数组维护一下 \(v_i\) 和 \(v_i \cdot i\) 即可. template <typename I> struct Fenwick { struct Node { I v0, v1; void add(I d0, I d1) { v0 += d0; v1 +=

树状数组学习

转载自:http://blog.csdn.net/int64ago/article/details/7429868 写下这个标题,其实心里还是没底的,与其说是写博帖,不如说是做总结.第一个接触树状数组还是两年前,用什么语言来形容当时的感觉呢?……太神奇了!真的,无法表达出那种感觉,她是那么的优雅,10行不到的代码,却把事情干的如此出色!没有了解她原理的前提下即使把代码倒背如流也理解不了!其中,我就是一直没搞懂地在使用她.时隔两年,又无意遇到了她,可能是两年的代码经验的积累,有了些新的认识,可以自

树状数组 学习笔记

树状数组可以用来求区间元素的和. 与前缀和做法不同,它支持值的修改. 比如说,现在我有一个数列a,要求你维护这个数列,使其支持两个操作. 1.改变数列第k项的值 2.查询从第i项到第j项的总值 暴力做法总是过不了所有点的,如果使用暴力,虽然操作1是O(1)的,但是操作2是O(n)的,没人对此复杂度满意. 假设原数列为a,我们的树状数组为c,那么,应该有下图的情况. 可以看出,每一个叶节点对应数组中的某个元素. c[i]为第i列树上最高的那个点. 数组c就是树状数组. 不难看出 对于每一个c[i]

树状数组_一维

// 模板水题 敌兵布阵 HDU - 1166 class TreeArray{ public: const static int cmaxn = 1e5; /// Todo: 修改区间的最大值 int cdate[cmaxn]; int max_sz; // 表示元素的个数 在init初始化 void init(int size) { memset(cdate, 0, sizeof(cdate)); max_sz = size; // 初始化本次样例的元素的个数 } void init(int

poj_1190 树状数组

题目大意 给定一个S*S的矩形,该矩形由S*S个1x1的单元格构成,每个单元格内可以放一个整数,每次有如下可能操作: (1)改变某个单位单元格中的数的大小 (2)查询由若干个连续单元格构成的X*Y的大小的矩形内所有数的总和 题目分析 典型的区间操作,而且是单点更新,区间查询.因此使用树状数组,不过应该使用二维树状数组.二维树状数组和一维其实没什么区别....     另:用线段树也做了一份,但是超时,果然树状数组在效率上还是略胜线段树的.下面给出树状数组的AC代码和线段树的TLE代码. 实现(c

树状数组入门

用office做了一张pdf - - 这是一维的情形,如果是二维,可以把每一行的一维树状数组看成一个节点,然后再把二维树状数组看成一维树状数组. 好文章:https://www.topcoder.com/community/data-science/data-science-tutorials/binary-indexed-trees/#prob 两道入门题:http://acm.hdu.edu.cn/showproblem.php?pid=1556 http://poj.org/problem

[扫描线+树状数组]解决矩形包含点的问题

今天做到第二题,大部分的思路都理解了之后最后剩下一个问题 zzx:“然后扫描线+树状数组搞一下就好了” 看到这两个算法就产生了一种我肯定会的错觉... 然后后来发现并不会的时候很惭愧... 然后十分感谢YDC,在之前完全陌生的情况下 我去问这样一个问题 超级超级超级耐心地给我解答  我问着每一个他们看起来显然的具体处理方法 突然发现真的像张老师说的:“你普及升提高的这条路没有怎么走,中间那块知识是空着的啊” 今天才切实体会到...但是或许正是这样今天学到这样的一个东西更让我觉得开心吧 树状数组解

【BZOJ】1452: [JSOI2009]Count 树状数组

Description Input Output Sample Input Sample Output 1 2 HINT 题解: 二维的树状数组啊+一维的颜色状态,然后直接做就好……实际上比照一维的树状数组就是多了一个for循环,然后查询操作的时候就相当于查询某一矩阵的大小,树状数组起到一个类似前缀和的作用.   1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <