恩,这是AC的第一道树状数组呢。

本蒟蒻以前遇到RMQ问题一般都用线段树或ST表,可惜ST表不支持在线修改,而线段树代码量又太大。

如今终于找到了折中方案:树状数组!!!!
代码量小,还支持修改!


树状数组也就是二叉索引树,又被称为Fenwick树,然而我个人认为它不能被严谨地成为树,因为充其量只是借用的树形结构的思想,于实现上有着较大的区别。

树状数组虽然运用范围没有线段树那么广,但是它的效率要高很多,比如线段树是$nlogn$,但树状数组是$logn$。

还有一点需要注意的是:树状数组可以区间查询,但不能运用于任意区间查询。这一点在后面会提到。


那么这个树状数组的基本思路就是

用节点ci储存和,比如:

- c1=a1
- c2=a1+a2
- c3=a3
- c4=a1+a2+a3+a4
- c5=a5
- c6=a5+a6
- c7=a7
- c8=a1+...+a8

当然这样子可能不是很容易看出内在的联系,因此不妨将其转化为二进制来观察:

- c0001=a0001
- c0010=a0001+a0010
- c0011=a0011
- c0100=a0001+a0010+a0011+a0100
- c0101=a0101
- c0110=a0101+a0110
- c0111=a0111
- c1000=a0001+...+a1000

是不是发现了什么?

没有吗?好吧。

事实上这里的规律就是cn=a(n–2^k+1)+...+an,这里的k指的是n二进制末尾0的数量

获取2^k的操作我们称之为lowbit,其实现如下:

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

有了lowbit操作之后,求和就很好写了:

 int query(int x){
int ans=;
while(x!=){
ans+=tree[x];
x-=lowbit(x);
}
return ans;
}

要注意一点,这里求的ans是区间[1,x]的和,想要[y,x]的和只能$query(x)-query(y-1)$。

因此我们回到了之前那个问题:树状数组不能解决所有区间查询,它只能解决如上的有关联的区间查询。

emmmm.....还有update操作:

 void update(int x,int k){
while(x<=n){
tree[x]+=k;
x+=lowbit(x);
}
}

这个在明白了树状数组的本质之后也很好理解,就不多做叙述了。


总的来说,树状数组挺好用的,值得一学。但切记,无论如何都必须掌握线段树,因为能用树状数组解决的都能用线段树,而反之不一定如此。

另附AC代码见下:

 #include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std; const int maxn=; int n,m;
int tree[maxn<<]; int lowbit(int k){
return k&(-k);
} void update(int x,int k){
while(x<=n){
tree[x]+=k;
x+=lowbit(x);
}
} int query(int x){
int ans=;
while(x!=){
ans+=tree[x];
x-=lowbit(x);
}
return ans;
} int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
int a;
scanf("%d",&a);
update(i,a);
}
for(int i=;i<=m;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(a==)update(b,c);
else printf("%d\n",query(c)-query(b-));
}
}

题解 P3374 【【模板】树状数组 1】的更多相关文章

  1. [模板] 树状数组 (C++ class)

    闲来无事(其实是打了两三道树状数组题),写了个树状数组模板…… /* Author: hotwords */ template<typename tp> class BinTree { p ...

  2. HDU 1166 线段树模板&树状数组模板

    HDU1166 上好的线段树模板&&树状数组模板 自己写的第一棵线段树&第一棵树状数组 莫名的兴奋 线段树: #include <cstdio> using nam ...

  3. 【洛谷 p3374】模板-树状数组 1(数据结构)

    题目:已知一个数列,你需要进行下面两种操作:1.将某一个数加上x:2.求出某区间每一个数的和. 解法:树状数组求前缀和. #include<cstdio> #include<cstd ...

  4. 【洛谷 p3368】模板-树状数组 2(数据结构)

    题目:已知一个数列,你需要进行下面两种操作:1.将某区间每一个数数加上x:2.求出某一个数的和. 解法:树状数组+前缀和优化.数组中每位存和前一位的数的差,这样区间修改只用改两位,单点询问就是求前缀和 ...

  5. POJ2299逆序对模板(树状数组)

    题目:http://poj.org/problem?id=2299 只能相邻两个交换,所以交换一次只会减少一个逆序对.所以交换次数就是逆序对数. ps:原来树状数组还可以记录后边lowbit位的部分和 ...

  6. 洛谷.3374.[模板]树状数组1(CDQ分治)

    题目链接 简易CDQ分治教程 //每个操作分解为一个有序数对(t,p),即(时间,操作位置),时间默认有序,用CDQ分治处理第二维 //对于位置相同的操作 修改优先于查询 //时间是默认有序的 所以可 ...

  7. 牛客网 暑期ACM多校训练营(第一场)J.Different Integers-区间两侧不同数字的个数-离线树状数组 or 可持久化线段树(主席树)

    J.Different Integers 题意就是给你l,r,问你在区间两侧的[1,l]和[r,n]中,不同数的个数. 两种思路: 1.将数组长度扩大两倍,for(int i=n+1;i<=2* ...

  8. CF459D Pashmak and Parmida's problem (树状数组)

    Codeforces Round #261 (Div. 2)   题意:给出数组A,定义f(l,r,x)为A[]的下标l到r之间,等于x的元素数.i和j符合f(1,i,a[i])>f(j,n,a ...

  9. 【poj 3167】Cow Patterns(字符串--KMP匹配+数据结构--树状数组)

    题意:给2个数字序列 a 和 b ,问按从小到达排序后,a中的哪些子串与b的名次匹配. a 的长度 N≤100,000,b的长度 M≤25,000,数字的大小 K≤25. 解法:[思考]1.X 暴力. ...

  10. 离线树状数组 hihocoder 1391 Countries

    官方题解: // 离线树状数组 hihocoder 1391 Countries #include <iostream> #include <cstdio> #include ...

随机推荐

  1. LeetCode hard 668. Kth Smallest Number in Multiplication Table(二分答案,一次过了,好开心,哈哈哈哈)

    题目:https://leetcode.com/problems/kth-smallest-number-in-multiplication-table/description/ 668. Kth S ...

  2. Paper Reading: Relation Networks for Object Detection

    Relation Networks for Object Detection笔记  写在前面:关于这篇论文的背景知识,请参考我前面的两篇随笔(<关于目标检测>和<关于注意力机制> ...

  3. python学习笔记第三章

    1.列表是由一系列特定顺序排列得元素组成,在python中用([])组成,列表得索引是从0开始,不是1 xu=['a','b',''c] print(xu) 访问列表的元素第一个元素 xu=['a', ...

  4. 5、AFM(Attention+FM)-----Attentional Factorization Machines:Learning the Weight of Feature Interactions via Attention Network

    1.摘要: 提出一个Attentional FM,Attention模型+因子分解机,其通过Attention学习到特征交叉的权重.因为很显然不是所有的二阶特征交互的重要性都是一样的,如何通过机器自动 ...

  5. POJ-3159 Candies 最短路应用(差分约束)

    题目链接:https://cn.vjudge.net/problem/POJ-3159 题意 给出一组不等式 求第一个变量和最后一个变量可能的最大差值 数据保证有解 思路 一个不等式a-b<=c ...

  6. Linux 文件系统挂载

    文件系统挂载简介  磁盘分区和格式化完成后,磁盘分区要想能够使用,就需要挂载,在挂载某个分区前需要先建立一个挂载点  挂载:将新的文件系统关联至当前根文件系统  卸载:将某文件系统与当前根文件系统的关 ...

  7. mariadb-增删改查怎么用

    MariaDB 数据类型 MariaDB数据类型可以分为数字,日期和时间以及字符串值. 使用数据类型的原则:够用就行,尽量使用范围小的,而不用大的 常用的数据类型 整数:int, (bit比整数还要小 ...

  8. 用shell写一个简单DHCP配置脚本

    轩轩写的这个小脚本,主要是可以进行对dhcp服务的安装.简单配置.开启.关闭/查看状态等情况 使用呢非常简单,按照步骤进行准确的设置就可以啦 #!/bin/bashyum -y install dhc ...

  9. 升级glibc的感慨,

    1. 直接升级 glibc是gnu发布的libc库,即c运行库.glibc是linux系统中最底层的api,几乎其它任何运行库都会依赖于glibc.glibc除了封装linux操作系统所提供的系统服务 ...

  10. python 模块一览

    一个模块可以对应一个文件 同一个模块,可以import多次,但只会被导入一次 模块的导入顺序 导入模块写在文件最上面 自己写的和内置的以及扩展的分开 顺序:内置,扩展,自己写的 按字母大小写排序 一行 ...