树状数组

【模板】树状数组 1

匿名 (未验证) 提交于 2019-12-02 23:49:02
题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入格式 第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。 接下来M行每行包含3个整数,表示一个操作,具体如下: 操作1: 格式:1 x k 含义:将第x个数加上k 操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和 输出格式 输出包含若干行整数,即为所有操作2的结果。 输入输出样例 输入 #1 复制 5 5 1 5 4 2 3 1 1 3 2 2 5 1 3 -1 1 4 2 2 1 4 输出 #1 复制 14 16 说明/提示 时空限制:1000ms,128M 数据规模: 对于30%的数据:N<=8,M<=10 对于70%的数据:N<=10000,M<=10000 对于100%的数据:N<=500000,M<=500000 样例说明: 故输出结果14、16 单点 修改,区间查询 #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int N=500005; int n,m; int a[N]; int lowbit(int l)

树状数组学习笔记

匿名 (未验证) 提交于 2019-12-02 23:49:02
ǰ׺֪ʶ lowbit=x&(-x) lowbit表示的是转换成二进制取第一个一和后面的0得到的数,树状数组经常用到lowbit(原理我也不知道) 树状数组只支持单点修改和前缀查询,其他可以通过拓展 时间复杂度分析: 单点修改O(log n) 前缀和查询O(log n) 树状数组操作: 1.lowbit(); 2.modify(x,d);//用于将点x加上数d 3.query(int x);//表示算出到x的前缀和 经典例题 1.洛谷P3374 裸的树状数组,直接按照需要的操作进行单点修改和前缀和查询,在利用前缀和的性质,来算出区间答案 cpp代码如下(代码中,a[i]表示一开始第i项的初始值,s[i]表示编号为i的数在维护的树状数组里,每个编号的数 #include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <cstring> #include <cstdlib> #include <iostream> #include<algorithm> #include<cmath> #include<stdlib.h> using namespace std;

【模板】树状数组 2

匿名 (未验证) 提交于 2019-12-02 23:49:02
5 5 1 5 4 2 3 1 2 4 2 2 3 1 1 5 -1 1 3 5 7 2 4 6 10 故输出结果为6、10 【解题思路】 这题也是一道很不错的题目,是一道区间修改,单点查询的树状数组(单点修改区间查询)改编 这道题利用了差分数组的思想,差分数组就是记录后一个数减去前一个数记录在差分数组中(即为程序中的ADD) 这样区间修改(l,r)时即可在l上加上修改值,r+1上减去修改值即可 单点查询即可直接查询即可 【code】 1 // luogu-judger-enable-o2 2 #include <cstdio> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 int n,m; 7 int a[500005],c[500005]; 8 inline int lowbit(int x){ 9 return x&(-x); 10 } 11 inline int GetSum(int x){ 12 int ans=0; 13 for(register int i=x;i!=0;i-=lowbit(i)) 14 ans+=c[i]; 15 return ans; 16 } 17 inline void Add(int x,int y){ 18 for(register int i=x

多维树状数组

匿名 (未验证) 提交于 2019-12-02 23:48:02
hdu2642 http://acm.hdu.edu.cn/showproblem.php?pid=2642 题目大意: 现在假设天空是一个二维平面(1000*1000)。坐标从(0,0)点开始。现在给出N条信息。 "B X Y",B为字符,x、y是整数,表示将坐标(x,y)的星星变亮。 "D XY",D为字符,x、y是整数,表示将坐标(x,y)的星星变暗。 "Q X1 X2 Y1 Y2",Q是字符,X1、X2、Y1、Y2是整数,表示问有多少颗星星在X1、X2、 Y1、Y2确定的矩形中。 思路: 建立一个二维的树状数组,单点更新,区间求值。其实和一维的差不多。只不过第i个元素变 为了第x行第y列的元素。更新和求值都是二维维护数组数组。再用一个二维数组Mark[][]表 示(x、y)处的星星的明暗情况。因为坐标是从(0,0)点开始的,而Lowbit(0) = 0,所以,另 所有的横纵坐标都加1,使坐标从(1,1)点开始。 #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std ; const int M = 1e3 + 3 ; int a [ M ][ M ], vis [ M ][ M ]; int lowbit ( int x ){

【树状数组】【P3372】 【模板】线段树 1

匿名 (未验证) 提交于 2019-12-02 23:48:02
Description 给定一个长度为 \(n\) 的序列,有 \(m\) 次操作,要求支持区间加和区间求和。 Limitation \(1 \leq n,~m \leq 10^5\) 序列元素值域始终在 long long 范围内。要求使用树状数组解决 Solution sb线段树板子题 一直听说这题有树状数组做法,今天刚刚明白。 首先区间加和区间求和可以转化成前缀修改和前缀求和。 考虑一个前缀加操作 update(x, v) 对一次前缀查询 query(y) 的贡献。 当 \(x \leq y\) 时,贡献为 \(x \times v\) 当 $ x > y$ 时,贡献为 \(y \times v\) 考虑分别维护这两种贡献。用第一个序列维护第一种贡献,每次进行 update(x, v) 时在序列 \(x\) 处加上 \(x \times v\) ,代表每个 查询 query(y) \((y \geq x)\) 都被加上了 \(x \times v\) 的贡献;用第二个序列维护第二种贡献,在进行 update(x, v) 时在 \(x\) 处加上 \(v\) ,代表每个查询 query(y) \((y < x)\) 都会被加上 \(y \times v\) 的贡献。 对于每个查询 query(y) ,其答案显然是 \(QA(y) + (QB(n) - QB(y)) \times

洛谷P3374 【模板】树状数组 1

匿名 (未验证) 提交于 2019-12-02 23:05:13
题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。 接下来M行每行包含3个整数,表示一个操作,具体如下: 操作1: 格式:1 x k 含义:将第x个数加上k 操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和 输出格式: 输出包含若干行整数,即为所有操作2的结果。 输入输出样例 输入样例#1: 复制 5 5 1 5 4 2 3 1 1 3 2 2 5 1 3 - 1 1 4 2 2 1 4 输出样例#1: 复制 14 16 说明 时空限制:1000ms,128M 数据规模: 对于30%的数据:N<=8,M<=10 对于70%的数据:N<=10000,M<=10000 对于100%的数据:N<=500000,M<=500000 样例说明: 故输出结果14、16 一道简单的模板题,没有什么特别解题思路。 AC代码: #include <iostream> using namespace std ; int tree [ 500004 ]; int n , m ; int lowbit ( int k ) { return k & (- k ); }

偏序问题总结(各种套路)

半城伤御伤魂 提交于 2019-12-02 21:42:11
因为一个傻逼T1没有切,所以我感觉我很傻逼。 所以在这里总结一些你们早就得心应手的方法,供我自己参考??? 一维偏序: 树状数组 排序递推 二维偏序: 运用排序解决一维,然后退化为一维偏序问题 主席树 二维树状数组(内存容易爆炸) 三维偏序: CDQ分治:(本质上也就是排序降1维,类似归并/双指针的方法处理1维,树状数组处理最后1维偏序) 化简题目或公式,去掉无用的一维,然后退化为二维偏序问题 四维偏序及更高: 这种题的数据范围肯定大不了,其实已经脱离了普通偏序的范畴 直接$O(n^2)$枚举 高维树状数组 各种套树 求大神们补充。。。我不会了。。。 来源: https://www.cnblogs.com/hzoi-DeepinC/p/11763510.html

逆序对模板(树状数组)

让人想犯罪 __ 提交于 2019-12-02 19:32:58
//P1908 逆序对 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int mxn=5e5+5; int a[mxn],c[mxn],b[mxn],f[mxn]; int n; inline int lowbit(int x){ return x&-x; } inline ll get(int x){ ll sum=0; for(;x;x-=lowbit(x)){ sum+=c[x]; } return sum; } inline void motify(int x,int y){ for(;x<=n;x+=lowbit(x)){ c[x]+=y; } } int main(){ cin>>n; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); b[i]=a[i]; } sort(b+1,b+n+1); int N=unique(b+1,b+n+1)-b-1; for(int i=1;i<=n;i++){ a[i]=lower_bound(b+1,b+N+1,a[i])-b; } for(int i=1;i<=n;i++){ motify(a[i],1); f[i]=i-get(a[i]); } ll ans=0; for(int i=1;i<=n

hdu3015树状数组

ε祈祈猫儿з 提交于 2019-12-02 17:11:24
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3015 题意:给定n组数,每组数有值x和值h,求n组数两两的val的总和。将所有x和所有h分别离散化(不去重)变成x'和h',val(i,j)为abs(x ' i -x ' j )*min(h i ' ,h j ' )。 如: x, h——>x',h' 10,100——>1,1 50,500——>4,4 20,200——>3,3 20,100——>1,1 思路:只要把n*n优化成n*logn就可以过。 tip1:按照h'的值sort,并动态加点,每次加的点如果是已加点中h'最小的,那么min()中要取的值就为h' tip2:离散化但是不去重,不需要unique tip3:关于abs()部分的处理,两棵树状数组,一棵统计数量,一棵统计sum。abs()值为(大于x'的sum-大于x'的数量*x')+(小于x'的数量*x'-小于x'的sum) tip4:res和sum树状数组均需要开long long 附上代码: #include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int maxn=1e5+10; int C1[maxn],C2[maxn

树状数组

。_饼干妹妹 提交于 2019-12-02 15:23:49
树状数组定义: 是一个查询和修改复杂度都为log(n)的数据结构。可以用于处理前缀和的问题,动态维护前缀和的工具 区间修改和区间查询用树状数组会显得很麻烦 相对而言用线段树会更灵活。 基本操作:求数列区间和,可以对数列单点进行操作。 前置知识: 差分数组 lowbit()操作:返回非负整数x 在二进制表示下,第一个1和后面的0表示的数值(十进制的值)。 int lowbit(int x) { return x&(-x); } /* -i 代表i的负数 计算机中负数使用对应的正数的补码来表示k表示i的二进制中末尾连续0的个数。 例如 : i=6(0110) 此时 k=1 -i=-6=(1001+1)=(1010) i&(-i)=(0010)=2=2^K k=1. C[i]=A[i-2^k+1]+A[i-2^k+2]+......A[i]; C[i]=A[i-lowbit(i)+1]+A[i-lowbit(i)+2]+......A[i]; */ 树状数组思想: 区间查询——》前缀和 ——》树结构维护(log 2 n) 树状数组 t[x] 保存以x为根的子树中叶节值的和 。 观察 t[x] 中每个x的二进制,每一层末尾零相同 ,零的个数即K对应覆盖的长度,覆盖长度就是lowbit(x)。 t [x] 的父节点为 t【x+lowbit[x]】 树的深度为 log 2 n+1 基本操作