树状数组

hdu 3450 树状数组 + dp

余生颓废 提交于 2020-03-27 06:30:37
转自 http://www.cppblog.com/baby-fly/archive/2010/08/03/122027.aspx?opt=admin 很显然是动态规划。dp[i]表示前i个数有多少个有效的子序列。那么 dp[i]=dp[i-1]+A。 A是前面i-1个数中,与i的差值不超过d的以该数结尾的有效的子序列的个数 的和。我们可以用另外一个数组sub[i]表示以i结尾的有效的子序列的个数。 dp与sub的不同之处是dp中的子序列不一定是以第i个数结尾的。 sub[i]= sigma sub[k] ,( abs(numk],num[i])<=d )。 由于求sub的时间复杂度为O(n^2),而n太大,因此需要离散化后用树状数组。 树状数组求和是一段连续的,而sub要求和的是位于区间[num[i]-d,num[i]+d],所以要对num排序,这样就能把 [num[i]-d,num[i]+d]放到连续的区间中。 #include < iostream > #include < algorithm > using namespace std; #define mod 9901 const int maxn = 100010 ; struct node { int value,index; }num[maxn]; int dp[maxn],cnt[maxn],tree[maxn];

树状数组 | 1057

心已入冬 提交于 2020-03-26 07:32:02
用哈希,把push的数x作为下标给hashTable(实则不存在,直接用tree树状数组记录数据)+1,pop则是以最后一个数x作为下标-1 。 树状数组和其原理不再赘述,需要注意的是最后的二分搜索(实则是lower_bound)中位数。 #include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <cstring> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm> #include <map> #define I scanf #define OL puts #define O printf #define F(a,b,c) for(a=b;a<c;a++) #define FF(a,b) for(a=0;a<b;a++) #define FG(a,b) for(a=b-1;a>=0;a--) #define LEN 100010 #define MAX (1<<30)+1 #define V vector<int> using namespace std; int tree[LEN]; int lowbit(int x){ return x&-x;

1057. Stack (30) - 树状数组

☆樱花仙子☆ 提交于 2020-03-26 06:32:48
题目如下: Stack is one of the most fundamental data structures, which is based on the principle of Last In First Out (LIFO). The basic operations include Push (inserting an element onto the top position) and Pop (deleting the top element). Now you are supposed to implement a stack with an extra operation: PeekMedian -- return the median value of all the elements in the stack. With N elements, the median value is defined to be the (N/2)-th smallest element if N is even, or ((N+1)/2)-th if N is odd. Input Specification: Each input file contains one test case. For each case, the first line contains a

树状数组

纵饮孤独 提交于 2020-03-26 04:20:10
  原文: http://www.cnblogs.com/ws5167/p/3903970.html   树状数组主要用于快速的更改某个点的值和查询某个区间的和,是一种比较小巧的数据结构.先看下图:           假设数组A[]是我们要操作的对象,则数组C[]则是数组A[]相对应的树状数组. 观察上图,我们得到数组C[]前八个值:   C[1]=A[1]   C[2]=A[1]+A[2]   C[3]=A[3]   C[4]=A[1]+A[2]+A[3]+A[4]   C[5]=A[5]   C[6]=A[5]+A[6]   C[7]=A[1]   C[8]=A[1]+A[2]+A[3]+A[4]+A[5]+A[6]+A[7]+A[8] .......    可以总结一个规律:当 i 为奇数时: C[i]=A[i];当 i 为偶数时: C[i]=A[i-2^k+1]+..A[i](k表示 i 最多有2的k次幂).   例如: 6的因子中有2的一次幂,等于2,所以C[6]=A[5]+A[6](由六向前数两个数的和),4的因子中有2的两次幂,等于4,所以C[4]=A[1]+A[2]+A[3]+A[4](由四向前数四个数的和).   对于任一个数组对应的树状数组有公式: C[n]=A[n-2^k+1]+....+A[n]( 其中k为n的二进制表示中从右往左数的0的个数 )  

Enemy is weak 树状数组

谁说我不能喝 提交于 2020-03-26 04:13:07
来源: http://codeforces.com/problemset/problem/61/E 题意:给你一些数,让求满足i < j < k 且num[i] > num[j] > num[k]的序列的个数,而且已知每个数都是不同的。 思路:这是CF上的一道题,由题意很容易联想到逆序数。实际上就是这样,这道题就是和逆序数有关。假如所给的序列为10 8 3 1,那么我们求出每个数的后面比其小的有多少个,对于该序列来说的话为3,2,1,0。然后我们再求出每个数前面有几个比其大的,对于 该序列来说是0,1,2,3。现在我们把对应的比其小的数的个数和比其大的数的个数相乘再相加就是所求的答案。 现在问题来了,用什么求逆序数。由于最多有100万个数,因此普通的方法求逆序数肯定超时。对于很多数求逆序数,一般有两种方法,归并排序或者是用树状数组求。我是用树状数组求得逆序数。先来说一下什么是树状数组。 树状数组,顾名思义,就是一个数组,但是该数组和普通数组的区别在于,此数组是树状的。树状的含义就是含有节点,该结点所含有的信息和普通数组不同。我们先来考虑普通数组,num[1],num[2],num[3],,,普通数组里的每个元素所含的值就是其本身,而树状数组则不同。num1[1]所包含的元素是其自身,num1[2]所包含的元素是普通num[1]+num[2]的和,num1[3]所包含的元素是num

CDQ分治【待补充,数据结构 - CDQ分治】

人盡茶涼 提交于 2020-03-25 02:59:10
为什么划分到数据结构Tag内呢,因为CDQ分治可以顶替复杂的高级数据结构,而且常数比较小。 待补充 相关资料 【教程】简易CDQ分治教程&学习笔记 CDQ学习笔记 权值树状数组/权值线段树 【算法讲堂】【电子科技大学】【ACM】CDQ分治 树状数组求逆序数 BZOJ 陌上花开 来源: https://www.cnblogs.com/shengwang/p/9857150.html

树状数组 (模板)

对着背影说爱祢 提交于 2020-03-21 23:43:55
树状数组的一维和二维模板 模板 int lowbit(int x){ return x & (-x);}void modify(int x,int add)//一维{ while(x<=MAXN) { a[x]+=add; x+=lowbit(x); }}int get_sum(int x){ int ret=0; while(x!=0) { ret+=a[x]; x-=lowbit(x); } return ret;}void modify(int x,int y,int data)//二维{ for(int i=x;i<MAXN;i+=lowbit(i)) for(int j=y;j<MAXN;j+=lowbit(j)) a[i][j]+=data;}int get_sum(int x,int y){ int res=0; for(int i=x;i>0;i-=lowbit(i)) for(int j=y;j>0;j-=lowbit(j)) res+=a[i][j]; return res;} 倆道模板题 hdu1166 地兵布阵 一维: View Code #include<stdio.h>#include<string.h>#include<stdlib.h>int c[50011],n;int lowbit(int x)//计算lowbit{ return x&(-x);

数据结构-树状数组

懵懂的女人 提交于 2020-03-08 09:50:27
数据结构-树状数组 参考资料 暂无 树状数组是较堆功能更强大的能解决 \(\texttt{RMQ}\) 问题的数据结构 。 数组数组的前置知识: 位运算 。 数组数组的功能:单点修改区间查询,区间修改单点查询(用差分)。 首先讲 \(lowbit(x)\) ,这是个位运算知识。表示 \(x\) 二进制下为 \(1\) 的最高位,如 \(lowbit((1110010)_2)=(10)_2\) , \(lowbit((110000)_2)=(10000)_2\) , \(\texttt{C++}\) 中的 \(x\&-x\) 正好能达到求 \(lowbit(x)\) 的效果。 然后树状数组中的 \(c\) 数组是个有跳跃性的前缀和数组,它通过 \(lowbit()\) 跳跃维护,然后通过 \(lowbit()\) 跳跃取值。原理较为复杂,不必深究。但是它有如下性质: 1.每次在 \(x\) 位置上 \(+y\) 时,可以这样维护 \(c[]\) : void fix(Tree&t,int n,int x,int y){ for(;x<=n;x+=low(x)) t.c[x]+=y; } 2.如下方法即可求出 \(\Sigma_1^xa[i]\) : int fsum(Tree&t,int x){ int res=0; for(;x;x-=low(x)) res+=t.c[x];

树状数组

生来就可爱ヽ(ⅴ<●) 提交于 2020-03-02 10:17:05
树状数组可以看作线段树的变形,不同于线段树可以计算区间和,区间最大/最小值,树状数组一般只能完成以下操作: 给定一个初始值全为0的数列 a 1 . . . a n a_1...a_n a 1 ​ . . . a n ​ 给定 i i i ,计算 a 1 + a 2 + . . . + a i a_1+a_2+...+a_i a 1 ​ + a 2 ​ + . . . + a i ​ ,即前缀和 给定 i i i 和 x x x ,执行 a i + = x a_i+=x a i ​ + = x 。 基于线段树的实现 如果使用线段树执行上述功能,只需要对介绍过的 RMQ 进行少量的修改,就可以实现,线段树每个节点维护区间的和。 接下来,我们重点关注给定区间始末 s , t s,t s , t ,如何求得 a s + a s + 1 + . . . + a t a_s+a_{s+1}+...+a_t a s ​ + a s + 1 ​ + . . . + a t ​ ,对于线段树,我们直接进行区间的迭代查询即可。但是有时这个效率依然是不够的 此时,如果我们维护前缀和 s u m [ i ] = a 0 + . . . + a i sum[i]=a_0+...+a_i s u m [ i ] = a 0 ​ + . . . + a i ​ ,那么只需要计算 s u m [ t ] − s

算法笔记:带修主席树(树套树)

試著忘記壹切 提交于 2020-02-28 04:48:00
从我短暂的ACMer生涯当中学到一件事———越是玩弄数据结构,就越会发现树的能力是有极限的… 除非超越树。 那就再套一层树吧!Wryyyyy!!! 最近打算研究一波树套树,平衡树怎么套还没搞懂,目前学习了一点套主席树的方法,平衡树的内容可能也会补在这吧。 众所周知,主席树维护的是一种类似前缀和的结构,每个节点都是包含了之前所有节点值的权值线段树,通过继承上一个节点权值线段树的部分结构以减少大量的空间和时间。 因为维护的是前缀和的结构,因此主席树满足可减性,在解决如静态区间第k小等问题中只需要取区间右端的树减区间左端的树即可得到仅包含有区间内值的权值线段树,这其实就类似于求一个序列的某个区间和可以用前缀和数组,区间右端的值减区间左端的值得到。 当然,以上都是废话,会写主席树的话肯定也知道这些东西。不过我还是要写出来,是因为想展示主席树其实本身也是一种“数据结构套数据结构”的形式,把每个节点的权值线段树抽象成点,主席树的上层就是一个简单的前缀和数组,下层使用权值线段树代替了前缀和数组中的每一个位置。而带修主席树不外乎就是把这个上层结构更换了一下,换成树状数组或线段树之类的其它数据结构。 以下通过两个简单的板子题展示下如何使用树状数组套主席树( 其实应该是树状数组套权值线段树 洛谷 P2617 Dynamic Rankings 题意: 给一个含有n个数的序列,需要支持两种操作: 1