首页 > 其他分享 >动态区间求和

动态区间求和

时间:2022-11-20 16:44:45浏览次数:42  
标签:set const 树状 求和 var int 数组 区间 动态

遇到问题,寻求解决问题的博客:Xenny

这里简单的随笔,是想整理一份自己看得懂的资料

**********************************************************************************************************************

题目描述:

请编写程序对数组a1​,a2​,...,an​进行如下操作 :

1 i x:给定i,x,将ai​ 加上x ;

2 l r:给定l,r,求al​+al+1​+...+ar​的值。

 

 

?????

解决方法:

(1)树状数组

关键:lowbit()

 在数组表示树的前提下,每个节点通过一定的规则来表示一段区间(根据具体要求可以将其改为最小值,最大值,和),通过少部分区间的修改来得到答案。

   

更新时需要注意的规则:C[i] = A[i - 2k+1] + A[i - 2k+2] + ... + A[i];   //k为i的二进制中从最低位到高位连续零的长度

 求和时需要注意的规则:

而根据上面的式子,容易的出SUMi = C[i] + C[i-2k1] + C[(i - 2k1) - 2k2] + .....;

 其中2k中的k表示的就是当前这个位置的i的二进制中从最低位到高位连续的0的长度。
求法 可以为 <code> int lowbit(const int& i){   return i&(-i); }  </code> 解决问题的代码: <code>

int lowbit(const int& set) {
return set & (-set);
}
void update(const int& set, const int& mod) {
for (int k = set; k <= number; k += lowbit(k)) {
tree_array[k] += mod;
}
}
long long getsum(int var) {
sum = 0;
while (var)
{
sum += tree_array[var];
var -= lowbit(var);
}
return sum;
}

</code>   **************************************************************************************************************************************

以上就是树状数组最基本的应用

**************************************************************************************************************************************

但是这种只是一种问题(单点更新,区间求和的一个实例)

那么类似的问题分为一下几类:

(1)单点更新,单点查询::直接数组应用

(2)单点更新,区间查询::正是这种区间求和问题,树状数组基本应用

(3)区间更新,区间查询::

已有基础上可能想到的方法:1,普通数组,一个个加,2,树状数组(在只学完求和的基础上),也是在区间里一个个改变,还没1快,多余操作太多

利用树状数组改进方法:

利用差分和(普通数组存储的是这个值和前一个值的差,树状数组中原本应该存值的和,现在存储差分的和)

也就是说通过差分构建树状数组:

就是把update(const int& set,const int& value);

中的value改为a[i]-a[i-1]

***其它的就和求和代码一样了

(4)区间更新,单点查询::

ni = 1A[i] = ∑ni = 1 ∑ij = 1D[j];

则A[1]+A[2]+...+A[n]

 

= (D[1]) + (D[1]+D[2]) + ... + (D[1]+D[2]+...+D[n]) 

 

= n*D[1] + (n-1)*D[2] +... +D[n]

 

= n * (D[1]+D[2]+...+D[n]) - (0*D[1]+1*D[2]+...+(n-1)*D[n])

所以上式可以变为∑ni = 1A[i] = n*∑ni = 1D[i] -  ∑ni = 1( D[i]*(i-1) );

所以维护两个树状数组::第一个每个节点:D[i],第二个每个节点:D[i]*(i-1)

代码:

<code>

#include<iostream>
using namespace std;
const int len = 1e5 + 2;
int array_raw[len];
long long tree_array1[len], tree_array2[len];
int N;
long long num;
int lowbit(const int& i) {
return i & (-i);
}
void update(const int& set, const int& var) {
for (int i = set; i <= N; i += lowbit(i)) {
tree_array1[i] += var;
tree_array2[i] += var * (set - 1);
}
}
long long getnum(const int& set) {
num = 0;
for (int i = set; i>0; i -= lowbit(i)) {
num += (set*tree_array1[i] - tree_array2[i]);
}
return num;

}
int main() {
int Q;
cin >> N >> Q;
int var;
for (int i = 1; i <= N; i++) {
cin >> array_raw[i];
update(i, array_raw[i]-array_raw[i-1]);
}
int var2,var1;
char varr;
while (Q--)
{
cin >> varr;
cout << "***" << varr << endl;
switch (varr)
{
case 'C': {
cin >> var >> var1 >> var2;
update(var,var2);
update(var1 + 1, -var2);
break;
}
case 'Q': {
cin >> var1 >> var2;
cout << getnum(var2) - getnum(var1 - 1) << endl;
break;
}
}
}
return 0;
}

</code>

(2)线段树

那为什么有了树状数组还要有线段树呢, 线段树比二叉树解决的问题更为广泛,我看到的树状数组解决的是区间的更新以及求和问题,但是线段树可以区间的更新,求和,求最大值,求最小值,等更多问题。

 

 

 

 

标签:set,const,树状,求和,var,int,数组,区间,动态
From: https://www.cnblogs.com/skiesclear-639/p/16908445.html

相关文章

  • P8839 [传智杯 #4 初赛] 组原成绩 ----- 简单加权求和
    题目描述花栗鼠科技大学(HualishuUniversityofScienceandTechnology,HUST)的计算机组成原理快要出分了。你现在需要计算你的组原成绩如何构成。具体来说,组原成绩分......
  • 799. 香槟塔 ----- 动态规划、模拟、逆向
    我们把玻璃杯摆成金字塔的形状,其中 第一层 有1个玻璃杯,第二层 有2个,依次类推到第100层,每个玻璃杯(250ml)将盛有香槟。从顶层的第一个玻璃杯开始倾倒一些香槟,......
  • 数据字典和动态性能视图
    数据字典存储在SYSTEM表空间中,包含对象定义、权限、用户角色等信息。USER_*用户所拥有的对象信息ALL_*用户能访问的对象信息DBA_*整个数据库中的对象信息系统中所......
  • Leetcode 799.香槟塔:动态规划+递归
    香槟塔:动态规划+递归题目来源:Leetcode22/11/20每日一题:799.香槟塔https://leetcode.cn/problems/champagne-tower我们把玻璃杯摆成金字塔的形状,其中第一层有1个玻......
  • 代码随想录第三十九天|动态规划
    今天是第三十九天,只有两道动态规划的题 62.不同路径 classSolution{publicintuniquePaths(intm,intn){int[][]path=newint[m][n];......
  • js 右下角动态提示消息框
    js:varsheyMsg=function(box,options){this.box=this.g(box);this.setOptions(options);this.init();}sheyMsg.prototype={ae:function(e......
  • 区间dp-Palindrome
    Palindrome题意:给一个字符串,问最少加上多少个字符,可以使这个字符串成为回文串思路一、直接dp(会爆内存)dp[i][j]表示区间[i,j]之间有最少需要加上多少个字符状态转移......
  • 34.计算求和 和 平均值
     #求和和计算平均值importpandasaspdpd.set_option('display.unicode.east_asian_width',True)data=[[100,90,80],[98,67,56],[56,56,45]]columns=['......
  • #yyds干货盘点# 动态规划专题:01背包
    1、简述:描述你有一个背包,最多能容纳的体积是V。现在有n个物品,第i个物品的体积为 ,价值为。(1)求这个背包至多能装多大价值的物品?(2)若背包恰好装满,求至多能装多大价值的物品?输......
  • 添加分类计数/求和列2(Power Query)
    问题:为数据添加按类别小计的计数和求和列let源=Excel.CurrentWorkbook(){[Name="表1"]}[Content],添加分类计数列=Table.AddColumn(源,"分类计数",each......