树状数组

[树状数组] 区间查询区间求和 洛谷P3372

房东的猫 提交于 2020-02-15 08:32:39
题目 题目链接:https://www.luogu.com.cn/problem/P3372 代码 # include <cstdio> # include <cstring> # include <cmath> # include <cstdlib> # include <cctype> # include <ctime> # include <iostream> # include <string> # include <map> # include <queue> # include <stack> # include <set> # include <vector> # include <iomanip> # include <list> # include <bitset> # include <sstream> # include <fstream> # include <complex> # include <algorithm> # if __cplusplus >= 201103L # include <unordered_map> # include <unordered_set> # endif # define ll long long # define lowbit(x) (-x)&x # define int long long using

树状数组模板--Color the ball

倾然丶 夕夏残阳落幕 提交于 2020-02-10 22:39:48
Color the ball HDU - 1556 N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色。但是N次以后lele已经忘记了第I个气球已经涂过几次颜色了,你能帮他算出每个气球被涂过几次颜色吗? Input 每个测试实例第一行为一个整数N,(N <= 100000).接下来的N行,每行包括2个整数a b(1 <= a <= b <= N)。 当N = 0,输入结束。 Output 每个测试实例输出一行,包括N个整数,第I个数代表第I个气球总共被涂色的次数。 Sample Input 1 3 2 1 1 3 2 2 4 3 3 5 3 6 1 1 7 1 2 8 1 3 9 0 Sample Output 1 1 1 3 2 1 思路不难,就是线段树||差分数组||普通树状数组||树状数组+差分的模板题 每次更新时区间各点+1,最后输出每个元素的值,总结来说就是 区间更新+单点查询 TLE版本,单点修改,肯定超时,因为需要每次遍历左端点到右端点去更新,无法保持O(logn)的时间复杂度 普通正解:update数组表示从1到x每个数 更新的次数 ,所以我们只需要update(L-1,-1)和update(R,1)表示[L,R]被更新的次数,相当于将

数据结构-树状数组

流过昼夜 提交于 2020-02-08 17:40:42
数据结构-树状数组 树状数组是较堆功能更强大的 RMQ 数据结构。 数组数组的前置知识: 位运算 。 数组数组的功能:单点修改区间查询,区间修改单点查询(用差分)。 首先讲 l o w b i t ( x ) lowbit(x) l o w b i t ( x ) ,这是个位运算知识。表示 x x x 二进制下为 1 1 1 的最高位,如 l o w b i t ( ( 1110010 ) 2 ) = ( 10 ) 2 lowbit((1110010)_2)=(10)_2 l o w b i t ( ( 1 1 1 0 0 1 0 ) 2 ​ ) = ( 1 0 ) 2 ​ , l o w b i t ( ( 110000 ) 2 ) = ( 10000 ) 2 lowbit((110000)_2)=(10000)_2 l o w b i t ( ( 1 1 0 0 0 0 ) 2 ​ ) = ( 1 0 0 0 0 ) 2 ​ , C++ \texttt{C++} C++ 中的 x & − x x\&-x x & − x 正好能达到求 l o w b i t ( x ) lowbit(x) l o w b i t ( x ) 的效果。 然后树状数组中的 c c c 数组是个有跳跃性的前缀和数组,它通过 l o w b i t ( ) lowbit() l o w b i t (

数星星_(树状数组)

无人久伴 提交于 2020-02-07 04:40:20
天空中有一些星星,这些星星都在不同的位置,每个星星有个坐标。如果一个星星的左下方(包含正左和正下)有 k颗星星,就说这颗星星是 k级的。 例如,上图中星星 5是 3 级的(1,2,4 在它左下),星星 2,4 是 1级的。 例图中有 1个 0 级,2 个 1 级,1 个 2 级,1 个 3级的星星。 给定星星的位置,输出各级星星的数目。 换句话说,给定 N个点,定义每个点的等级是在该点左下方(含正左、正下)的点的数目,试统计每个等级有多少个点。 输入格式 第一行一个整数 N,表示星星的数目;接下来 N行给出每颗星星的坐标,坐标用两个整数 x,y表示; 不会有星星重叠。星星按 y坐标增序给出,y 坐标相同的按 x坐标增序给出。 输出格式 N行,每行一个整数,分别是 0 级,1 级,2 级,……,N−1级的星星的数目。 数据范围 1≤N≤15000, 0≤x,y≤32000 输入样例: 5 1 1 5 1 7 1 3 3 5 5 输出样例: 1 2 1 1 0 首先,题中星星的坐标是先进行纵坐标,然后进行横坐标,,也就是说对于每一个星星,他的星星都是已经给出的星星中纵坐标最大的,也就是说 y 坐标是最大的,没有星星会在他的上面,所以,只需要考虑有多少个星星的横坐标是在这个星星的左侧,也就只需要考虑 x 坐标,因为树状数组从 1 开始,所以要把每一个 x 坐标加上 1 # include

HDU5792 World is Exploding(树状数组+容斥原理)

陌路散爱 提交于 2020-02-04 16:13:21
根据对题目的观察,我们可以发现本题其实可以抽象成正序对和逆序对的个数的题目 这就能让我们联想到使用树状数组来解决问题 另外本题需要离散化,因为数据过大。 我们可以先求取所有情况,减去不合法的情况,也就是所谓的容斥原理,那么那些是不满足的呢? 我们从题目看出他要是四元组,而我们用乘法原理求出的情况,包含很多满足情况的三元组 比如Aa<=Ab==Ad<Ac这种情况只有三元组,而我们在计算中也算过了,所以把这些情况减去即可 #include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<vector> #include<string> #include<cstring> #include<map> using namespace std; typedef long long ll; const int N=3e5+10; int a[N]; int n; int tr[N]; int li[N],ri[N]; int lx[N],rx[N]; vector<int> num; int find(int x){ return lower_bound(num.begin(),num.end(),x)-num.begin()+1; } int lowbit(int x){ return x&-x;

树状数组(入门篇)

不问归期 提交于 2020-02-01 20:23:55
学习过线段树之后,应该会觉得线段树在各种维护问题上代码量比较大,而且比较麻烦。主要原因就是因为线段树把每个大区间都分成两个小区间,直到分成单独点。但是在实际操作的时候,很多申请的区间节点都是用不上的,造成了空间的浪费,那么如何解决这一问题呢? 先引入前缀和的概念: 前缀和:对于某一数组a[n],其中前缀和数组s[n]定义为s 0 =0,s i =a[1]+…+a[i](1<=i<=n)。即a数组的前i(1<=i<=n)项和叫做该数组的前缀和。容易知道,a数组中的任意区间和都可以通过该前缀树组中的元素相减得到 有了前缀和,我们可以简化下列线段树: 怎么简化呢?我们把该线段树上的所有的右子树去掉,只保留所有的左子树,这样之后,右子树本该保留的值就拿父节点保留的值减去左子树保留的值可以得到 如上图,蓝色部分是线段树删去的保存的叶子节点,箭头表示它保存在上面的父区间中。现在的结构就叫做树状数组,下图是更直观的树状数组图: 我们可能会想,为什么要去掉右子树,去掉所有的左子树不行吗?在解释这个问题之前,我们先看下面这个函数 Lowbit()函数 Lowbit(x):将x在二进制分解下最低位的大小,通俗来讲就是找到从右向左第一个1所在位次k,其对应的大小为2 k 例如Lowbit(9),9的2进制为1001,显然最低位的大小为2 0 =1 下面给出一个结论来求Lowbit(x)

楼兰图腾(树状数组)

耗尽温柔 提交于 2020-01-30 23:08:41
楼兰图腾 楼兰图腾 在完成了分配任务之后,西部314来到了楼兰古城的西部。 相传很久以前这片土地上(比楼兰古城还早)生活着两个部落,一个部落崇拜尖刀(‘V’),一个部落崇拜铁锹(‘∧’),他们分别用V和∧的形状来代表各自部落的图腾。 西部314在楼兰古城的下面发现了一幅巨大的壁画,壁画上被标记出了N个点,经测量发现这N个点的水平位置和竖直位置是两两不同的。 西部314认为这幅壁画所包含的信息与这N个点的相对位置有关,因此不妨设坐标分别为(1,y1),(2,y2),…,(n,yn),其中y1~yn是1到n的一个排列。 西部314打算研究这幅壁画中包含着多少个图腾。 如果三个点(i,yi),(j,yj),(k,yk)满足1≤i<j<k≤n且yi>yj,yj<yk,则称这三个点构成V图腾; 如果三个点(i,yi),(j,yj),(k,yk)满足1≤i<j<k≤n且yi<yj,yj>yk,则称这三个点构成∧图腾; 西部314想知道,这n个点中两个部落图腾的数目。 因此,你需要编写一个程序来求出V的个数和∧的个数。 输入格式 第一行一个数n。 第二行是n个数,分别代表y1,y2,…,yn。 输出格式 两个数,中间用空格隔开,依次为V的个数和∧的个数。 数据范围 对于所有数据,n≤200000,且输出答案不会超过int64。 输入样例: 5 1 5 3 2 4 输出样例: 3 4 题意:

二维数组数组详解

ぐ巨炮叔叔 提交于 2020-01-30 12:49:31
转载自: 胡小兔博客,https://www.cnblogs.com/RabbitHu/p/BIT.html %%大连市理科状元。 “高级”数据结构——树状数组! ※本文一切代码未经编译,不保证正确性,如发现问题,欢迎指正! 1. 单点修改 + 区间查询 最简单的树状数组就是这样的: void add(int p, int x){ //给位置p增加x while(p <= n) sum[p] += x, p += p & -p; } int ask(int p){ //求位置p的前缀和 int res = 0; while(p) res += sum[p], p -= p & -p; return res; } int range_ask(int l, int r){ //区间求和 return ask(r) - ask(l - 1); } 2. 区间修改 + 单点查询 通过“差分”(就是记录数组中每个元素与前一个元素的差),可以把这个问题转化为问题1。 查询 设原数组为 a [ i ] a[i], 设数组 d [ i ] = a [ i ] − a [ i − 1 ] ( a [ 0 ] = 0 ) d[i]=a[i]−a[i−1](a[0]=0),则 a [ i ] = ∑ i j = 1 d [ j ] a[i]=∑j=1id[j],可以通过求 d [ i ] d[i

树状数组与线段树(二)

流过昼夜 提交于 2020-01-28 16:16:03
树状数组 1.小朋友排队 n 个小朋友站成一排。 现在要把他们按身高从低到高的顺序排列,但是每次只能交换位置相邻的两个小朋友。 每个小朋友都有一个不高兴的程度。 开始的时候,所有小朋友的不高兴程度都是 0 。 如果某个小朋友第一次被要求交换,则他的不高兴程度增加 1 ,如果第二次要求他交换,则他的不高兴程度增加 2 (即不高兴程度为 3 ),依次类推。当要求某个小朋友第 k 次交换时,他的不高兴程度增加 k 。 请问,要让所有小朋友按从低到高排队,他们的不高兴程度之和最小是多少。 如果有两个小朋友身高一样,则他们谁站在谁前面是没有关系的。 输入格式 输入的第一行包含一个整数 n ,表示小朋友的个数。 第二行包含 n n 个整数 H 1 , H 2 , … , H n ,分别表示每个小朋友的身高。 输出格式 输出一行,包含一个整数,表示小朋友的不高兴程度和的最小值。 数据范围 1 ≤ n ≤ 100000 0 ≤ H i ≤ 1000000 输入样例: 3 3 2 1 输出样例: 9 样例解释 首先交换身高为3和2的小朋友,再交换身高为3和1的小朋友,再交换身高为2和1的小朋友,每个小朋友的不高兴程度都是3,总和为9。 解题思路:解题关键就是找到最少的交换次数,我们可能会想到冒泡排序法,他就是通过不断的交换排序来实现的,因此我们可以大胆的假设一些规律,最少的交换次数==逆序对的个数。

树状数组

南楼画角 提交于 2020-01-28 00:45:03
转载: https://www.cnblogs.com/xenny/p/9739600.html 练习 : loj 130-134 先来看几个问题吧。 1.什么是树状数组? 顾名思义,就是用数组来模拟树形结构呗。那么衍生出一个问题,为什么不直接建树?答案是没必要,因为树状数组能处理的问题就没必要建树。和Trie树的构造方式有类似之处。 2.树状数组可以解决什么问题 可以解决大部分基于区间上的更新以及求和问题。 3.树状数组和线段树的区别在哪里 树状数组可以解决的问题都可以用线段树解决,这两者的区别在哪里呢?树状数组的系数要少很多,就比如字符串模拟大数可以解决大数问题,也可以解决1+1的问题,但没人会在1+1的问题上用大数模拟。 4.树状数组的优点和缺点 修改和查询的复杂度都是O(logN),而且相比线段树系数要少很多,比传统数组要快,而且容易写。 缺点是遇到复杂的区间问题还是不能解决,功能还是有限。 一、树状数组介绍 二叉树大家一定都知道,如下图 如果每个父亲都存的是两个儿子的值,是不是就可以解决这类区间问题了呢。是的没错,但是这样的树形结构,叫做线段树。 那真的的树形结构是怎样的,和上图类似,但省去了一些节点,以达到用数组建树。 黑色数组代表原来的数组(下面用A[i]代替),红色结构代表我们的树状数组(下面用C[i]代替),发现没有,每个位置只有一个方框