树状数组

luoguP5666 树的重心 树状数组

£可爱£侵袭症+ 提交于 2020-01-26 20:12:23
这道题在家里仔细想想还是挺好想的... 考场的时候还是要镇定,给每道题要安排足够的思考时间. code: #include <cstdio> #include <cstring> #include <vector> #include <string> #include <algorithm> #define N 500004 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; int n; namespace BIT { int C[N]; int lowbit(int t) { return t&(-t); } void clr() { for(int i=0;i<N;++i) C[i]=0; } void update(int x,int v) { if(x<=0) return; while(x<N) C[x]+=v,x+=lowbit(x); } int ask(int x) { int re=0; for(int i=x;i>0;i-=lowbit(i)) re+=C[i]; return re; } int query(int l,int r) { l=max(1,l),r=min(r,n); return l>r?0:ask(r)-ask(l-1);

树状数组

烂漫一生 提交于 2020-01-26 18:30:52
基本用途:维护序列的前缀和。 对于给定的序列a,建立一个数组c,其中c[x]保存序列a的区间[x-lowbit(x)+1,x]中所有数的和,其中 lowbit(x)指:x的二进制下最小的2的次幂,如:       lowbit(7)=1,lowbit(6)=2,lowbit(5)=1,lowbit(4)=4 该结构满足一下性质: 每个内部节点c[x]保存以它为根的子树中所有叶节点的和 每个内部节点c[x]的子节点个数等于lowbit(x)的位数 除树根外,每个内部节点c[x]的父节点是c[x+lowbit(x)] 树的深度为o(logN) 初始化 建立一个全为0的数组c,对位置x初始化为a[x],执行add(x,a[x]) 时间复杂度O(NlogN) void add(int x,int y){ for(;x<=n;x+=x&-x) c[x]+=y; } 单点增加 对位置x增加a[x],执行add(x,a[x]) void add(int x,int y){ for(;x<=n;x+=x&-x) c[x]+=y; } 查询前缀和 (1~x) 时间复杂度O(logN) int ask(int x){ int res=0; for(;x;x-=x&-x) res+=c[x]; return res; } 若查询序列a的区间[l,r]中所有数的和,只需计算ask(r)-ask(l-1)

树状数组学习笔记

我是研究僧i 提交于 2020-01-25 20:28:10
目录 树状数组学习笔记 树状数组 lowbit 操作 单点修改和区间查询 单点修改 区间查询 例题1 P3374 【模板】树状数组 1 区间修改和单点查询 差分思想 例题2 P3368 【模板】树状数组 2 区间修改和区间查询 区间查询 例题3 P3372 【模板】线段树 1 简单应用 P1908 逆序对 P1972 [SDOI2009]HH的项链 P5673 【SWTR-02】Picking Gifts P3369 【模板】普通平衡树 树状数组学习笔记 树状数组 本文参考视频: https://www.bilibili.com/video/av69667943?from=search&seid=204489840113652018   lowbit 操作 int lowbit(int x) { return x & (-x); } \(lowbit\) 操作是为了求出一个数字 \(x\) 在二进制形态下,最低位的 \(1\) 的大小。 例如 \((110100)_2\) 中最低位 \(1\) 的大小是 \((100)_2\) 。 \(lowbit\) 求解的方法是,先将 \(x\) 的二进制按位取反,然后 \(+1\) ,再按位与原数字。 例如: \((110100)_2\) 按位取反 \((001011)_2\) \(+1\) \((001100)_2\) 按位与原数 \(

树状数组

我的未来我决定 提交于 2020-01-23 00:21:55
树状数组是一种有效更新元素并计算前缀和的数据结构。 给定一个数组,需要进行上述操作。朴素算法是线性时间复杂度,而树状数组允许在O(logn)的时间内执行这两个操作。 假设原数组为a,与之等价的树状数组为c,有如下关系: $\begin{cases} \ c[x]=\sum_{i=x-lowbit(x)+1}^{x}a[i] \\ \ lowbit(x)=x\&(-x) \end{cases}$ lowbit(x)截取x的二进制形式中最低位的1及其后面的0,因此x-lowbit(x)可以抹去x的二进制形式中最低位的1。 比如(以下数值均为二进制),lowbit(10110)=10,10110-lowbit(10110)=10100。 等价关系的图像形式如图所示: 其中每个结点的值都等于其子孙结点值的和。 由图可以看出更新操作只需不断向上修改父结点,由关系式得出计算前缀和操作只需以lowbit为跨度求c数组的和。既然操作是抬升或消除二进制中的尾1,那么总操作次数必定小于等于二进制位数,这是对数级别的。 #define lowbit(x) x&-x const int S; int c[S] = {0}; void add(int x, int d){ while(x <= S) c[x] += d,x += lowbit(x); } int sum(int x){ int ret =

信息学.学习计划/注意事项

别来无恙 提交于 2020-01-20 23:45:58
<学习计划> 一、重点学习新算法 1.平衡树splay,动态树LCT 2.(任意模数)NTT 3.莫队算法 4.带修主席树(树状数组套主席树),线段树/树状数组套平衡树 5.后缀数组/后缀自动机 二、刷题,复习、巩固在OJ上打星号的题目 <注意事项> 1.考试时无论题目有多难,都要努力想正解,不要理会别人,保持心态,想不出正解时要全力打暴力。 2.比赛开始时建各种文件夹要快,不耽误时间,离比赛结束15-20分钟时检查程序,把握好时间。 来源: https://www.cnblogs.com/mgh792821814/p/12219832.html

树状数组学习笔记

做~自己de王妃 提交于 2020-01-19 00:16:59
本文是笔者学完树状数组后对树状数组进行的一个学习总结,如有纰漏或者错误之处,还望读者不吝指教,不胜感激! 一、树状数组的概念: 所谓树状数组(Binary Indexed Tree),从字面意思来讲,就是用数组来模拟树形结构。也就是说它可以将线性结构转化为树形结构,从而实现跳跃式的扫描。所以它一般应用于解决动态前缀和问题。 二、树状数组一般可以解决的问题: 树状数组可以解决大部分基于区间上的更新和求和问题。但功能有限,遇到一般的复杂问题是不能解决的。 三、和线段树的区别: 所有可以用树状数组解决的问题都可以用线段树解决。但树状数组的代码复杂度明显优于线段树。所以可以使用树状数组解决的问题都可以尽量考虑用树状数组解决。(当然,神牛请随意) 四、时间复杂度和空间复杂度: 树状数组修改和查询的时间复杂度都是O(logN),空间复杂度为O(N) 下面我将从树状数组的创建到树状数组可以实现的各个功能开始逐一讲解。 1、树状数组的创建: 讲解二叉树的结构之前,我先引入二叉树的结构,如图下图所示: 这样每一个父亲节点都存的是两个子节点的值,那就可以解决一般的基于区间的查询和修改问题,但这样的树形结构是线段树,不是树状数组。所以树状数组是一个什么样的树形结构呢? 首先,我们把二叉树的结构变形一下: 之后,在删掉部分结点,如下图所示: 黑色数组表示原来的数组A[i],红色代表树状数组C[i],看上图

大数据求逆序数(树状数组)

孤者浪人 提交于 2020-01-18 03:02:02
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> typedef long long ll; using namespace std; ll sum[500050],n; struct node{ ll lf; ll rg; }a[500050]; ll cmp(node x,node y) { if(x.lf==y.lf) return x.rg<y.rg; return x.lf<y.lf; } ll lowbit(ll x) { return x&(-x); } ll Point_change(ll x) { while(x<=n) { sum[x]=sum[x]+1; x=x+lowbit(x); } } ll get_sum(ll x) { ll res=0; while(x>0) { res=res+sum[x]; x=x-lowbit(x); } return res; } int main() { ll sm; while(scanf("%lld",&n)) { if(n==0) break; memset(sum,0,sizeof(sum)); for(ll i=1;i<=n;i++) { scanf("%lld",&a[i].lf); a[i].rg=i; }

树状数组解题模版

送分小仙女□ 提交于 2020-01-16 08:14:23
树状数组 一、树状数组概念 Binary Indexed Tree ,用于维护前缀信息的结构,对前缀信息处理也十分高校,用于解决前缀信息问题和区间类问题。 比如:给定一个数组,实现两个函数 update (int index,int val),将数组下标为index的元素改为val querySum (int start,int end),返回区间内元素和 这两个用线段树求过很多遍了。树状数组也是通过前缀和的思想来完成单点更新和区间查询。它比线段树用的空间更小,速度更快。 二、树状数组算法分析 注意 :树状数组的下标从 1 开始计数。定义数组 C 是一个对原始数组 A 的预处理数组。 由原数组构造树状数组 结论 :C[i]来自几个数组A中的元素:取决于i的二进制末尾有几个连续的0。比 如有k个0,那么C[i]来自2 k 个A中的元素。 如果i是当前位置,当前有2 k 个来自A中的元素,有哪2 k 个呢?就是从C[i]的正下方出发,往前数2 k 个,C[i]就是这2 k 个数的和。 定义一个 lowbit(i) = 2^k 函数,就是把下标i传到函数中来,返回2 k ,lowbit表示C[i]这个数值是由A中的多少个元素相加得来的。(根据上面一段,你还能找到这几个元素是啥,从C[i]的正下方开始往前数2 k 个) 怎么找父亲节点? i+lowbit(i) = 父亲 比如C[4]

树状数组的一些理解

99封情书 提交于 2020-01-14 11:04:48
树状数组中的 l o w b i t lowbit l o w b i t 的一些具体意思,有一点感悟。 原理:这个百度上都有,就不说了。 假设树状数组为 c [ ] c[] c [ ] ,原数组为 a [ ] a[] a [ ] , 1 − i 1-i 1 − i 的和数组为 s u m [ i ] sum[i] s u m [ i ] 。 则经过观察有: c [ i ] = a [ i − 2 k + 1 ] + a [ i − 2 k + 2 ] + . . . + a [ i ] c[i]=a[i-2^{k}+1]+a[i-2^{k}+2]+...+a[i] c [ i ] = a [ i − 2 k + 1 ] + a [ i − 2 k + 2 ] + . . . + a [ i ] s u m [ i ] = c [ i ] + c [ i − 2 k 1 ] + c [ i − 2 k 1 − 2 k 2 ] + . . . + c [ 0 ] sum[i]=c[i]+c[i-2^{k1}]+c[i-2^{k1}-2^{k2}]+...+c[0] s u m [ i ] = c [ i ] + c [ i − 2 k 1 ] + c [ i − 2 k 1 − 2 k 2 ] + . . . + c [ 0 ] 这里的 l o w b i t ( x )

cf#590 D 二维树状数组

久未见 提交于 2020-01-14 01:00:42
题意 给一个10^5之内的字符串(小写字母)时限2s 输入n,有n个操作 (n<10^5) 当操作是1的时候,输入位置x和改变的字母 当操作是2的时候,输入区间l和r,有多少不同的字母 思路 二维树状数组 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<map> 6 #define lowbit(x) x&(-x) 7 using namespace std; 8 const int maxn=1e5+10; 9 char s[maxn]; 10 int l,n,yi,er,san; 11 char c; 12 struct node{ 13 int tr[maxn]; 14 void inint(){ 15 memset(tr,0,sizeof(tr)); 16 } 17 void updata(int x,int y){ 18 for(int i=x; i<=l; i+=lowbit(i)){ 19 tr[i]+=y; 20 } 21 } 22 int geshu(int x,int y){ 23 int sum1=0,sum2=0; 24 for(int i=x; i>0; i-=lowbit(i)){ 25 sum1+=tr[i]; 26 }