首页 > 其他分享 >超级树状数组

超级树状数组

时间:2024-09-19 20:47:03浏览次数:7  
标签:limits 树状 int 超级 lint 数组 sum

众所周知:

  • 线段树的代码长,常数大;
  • 树状数组的代码短,常数小,甚至可以通过 \(10^6\) 量级的数据。

所以,能不能实现一个可以区间修改、区间查询的树状数组呢?


由于涉及区间操作,考虑差分数组 \(\{d_n\}\)。

区间修改

对于原数组 \([l,r]\) 区间每个数加 \(w\)。

可以转化为两次单点修改,即 \(l\) 单点处加 \(+w\),\(r+1\) 单点处加 \(-w\)。

区间查询

对于原数组 \([l,r]\) 区间求和。

显然 \(\sum\limits_{i=l}^r a_i\) 可以差分为两个 \([1,u]\) 的前缀求和。

\[\sum\limits_{i=1}^{u} a_i =\sum\limits_{i=1}^u\sum\limits_{j=1}^{i}d_j \]

观察每一个 \(a_i=\sum\limits_{j=1}^{i}d_j\),可以发现

\[\begin{aligned} a_1&=d_1\\ a_2&=d_1+d_2\\ a_3&=d_1+d_2+d_3\\ \cdots\\ a_u&=d_1+d_2+d_3+\cdots+d_u \end{aligned} \]

所以 \(d_1\) 的贡献为 \(u\),\(d_2\) 的贡献为 \(u-1\),\(d_3\) 的贡献为 \(u-2\),……,\(d_u\) 的贡献为 \(1\)。

故可得 \(d_k\) 的贡献为 \(u-j+1\)。

\[\sum\limits_{i=1}^u\sum\limits_{j=1}^{i}d_j=\sum\limits_{j=1}^{u}d_j(u-j+1) \]

发现 \(u+1\) 的值是固定的,可以提取出来:

\[\sum\limits_{j=1}^{u}d_j(u-j+1)=\Big((u+1)\sum\limits_{j=1}^{u}d_j\Big)-\Big(\sum\limits_{j=1}^{u}(j\times d_j)\Big) \]

因此同时使用两个树状数组维护 \(\{d_n\}\)、\(\{n\times d_n\}\) 即可,该技巧即为超级树状数组。

代码实现

typedef long long lint;
lint sum(int p, lint *t) { // 查询 t 中 [1,p] 之和
	lint res = 0;
	for (int i = p; i; i -= lowbit(i))
		res += t[i];
	return res;
}

lint ask(int p) {
	return sum(p, d) * (p + 1) - sum(p, f);
}

lint query(int l, int r) {
	return ask(r) - ask(l - 1);
}

void add(int p, lint x, lint *t) {
	for (int i = p; i <= n; i += lowbit(i)) t[i] += x;
}

void update(int l, int r, lint x) {
	add(l, x, d), add(r + 1, -x, d);
	add(l, x * l, f);
	add(r + 1, -x * (r + 1), f);
}

标签:limits,树状,int,超级,lint,数组,sum
From: https://www.cnblogs.com/oier-wst/p/18421299/super-bit

相关文章

  • 977_有序数组的平方
    977_有序数组的平方【问题描述】给你一个按非递减顺序排序的整数数组nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。示例一:输入:nums=[-4,-1,0,3,10]输出:[0,1,9,16,100]解释:平方后,数组变为[16,1,0,9,100]排序后,数组变为[0,1,9,16,100]示例二:输......
  • java的二维数组
    二维数组的初始化 二维数组的进行for循环时的判断条件怎么确定的呢?  因为在二维数组是特殊的一维数组,c语言中二维数组首元素的代表的是地址,而首元素代表的是一组一维数组,计算首元素的长度也就是计算二维数组的行下标为0的一维数组的长度所以判断数组名的长度也就是判断......
  • 剖析:数组
    目录1. 一维数组2. 二维数组3. 字符数组3.1 计算数组(字符串)中字符个数3.1.1 sizeof3.1.2 strlen3.1.3 循环找寻​编辑3.1.4 指针-指针4. 变长数组5. 冒泡排序6. qsort排序7. 杨辉三角 8.  二分查找 生活中有非常多的数据,也可能是......
  • 【Go】Go语言中的数组基本语法与应用实战
    ✨✨欢迎大家来到景天科技苑✨✨......
  • 信息学奥赛初赛天天练-92-CSP-S2023阅读程序2-动态数组、反转函数、埃氏筛法、欧拉筛
    2023CSP-S阅读程序2判断题正确填√,错误填⨉;除特殊说明外,判断题1.5分,选择题3分,共计40分)01#include<iostream>02#include<cmath>03#include<vector>04#include<algorithm>05usingnamespacestd;0607longlongsolve1(intn){08vector<boo......
  • 33. 搜索螺旋数组
    题目描述:整数数组nums按升序排列,数组中的值互不相同。在传递给函数之前,nums在预先未知的某个下标k(0<=k<nums.length)上进行了旋转,使数组变为[nums[k],nums[k+1],...,nums[n-1],nums[0],nums[1],...,nums[k-1]](下标从0开始计数)。例如,[0,1,2,4,5,6,7]在......
  • 【洛谷 P5730】【深基5.例10】显示屏 题解(数组+循环)
    【深基5.例10】显示屏题目描述液晶屏上,每个阿拉伯数字都是可以显示成的点阵的(其中X表示亮点,.表示暗点)。现在给出数字位数(不超过)和一串数字,要求输出这些数字在显示屏上的效果。数字的显示方式如同样例输出,注意每个数字之间都有一列间隔。输入格式第一行输入一个正整数,表示数......
  • 【LeetCode Hot 100】4. 寻找两个正序数组的中位数
    题目描述要求出两个数组的中位数,第一想法当然是将这两个数组进行归并排序,然后直接得到排序后长数组的中位数。由于本题的两个数组都是排序后的数组,因此省去了排序的步骤。这种方法的时间复杂度为\(O(m+n)\),空间复杂度由于要存储排序后的长数组,所以也是\(O(m+n)\)。有没有相对更......
  • 34. 在排序数组中查找元素的第一个和最后一个位置
    思路先判断target是否存在列表中,不存在直接输出存在,则找出第一个等于target值的列表位置,即目标值在列表中的开始位置接着在当前位置继续往下查找,找到最后一个目标值等于列表值的位置(也可用二分查找找到等于target值的位置+往前、往后找到开始、结束位置,但会超限,可参考(......
  • 【C总集篇】第八章 数组和指针
    文章目录第八章数组和指针数组数组回顾初始化数组初始化数组介绍初始化失败案例部分初始化自动匹配数组给数组赋值数组边界指定数组大小多维数组二维数组的定义二维数组的初始化指针与数组函数数组与指针函数数组与指针初了解使用指针形参指针操作八种基本指针......