pku3468 线段树 区间求和

本文深入解析了一种特殊的线段树实现方法,该方法用于处理区间更新及查询问题。通过实例详细介绍了线段树节点结构的设计思路,以及初始化、更新和查询操作的具体实现,并附带源代码说明。

A Simple Problem with Integers

又一道线段树,与前两道差异比较大,每次update操作中,是将一段区间的每一个值都加上某一个值,而不是简单的覆盖。


  
struct node{
int l, r, cover;
__int64 sum;
__int64 key;
}st[NN
* 8 ];

在这里,我用sum表示区间[l, r]的所有数的和,包括附加的值;key表示update中对区间[l, r]的附加值,cover表示此区间上有没有附加值。引用名词:当前区间指的是[st[id].l,st[id].r], 要查找的区间是[l, r], 代码中我总结到有5点值得我注意,值得我学习的地方:

key1:在初始化的时候,递归返回的时候将子区间的值加起来,保存到当前区间,作为初始化值。

key2:Update时,如果找到正好匹配的区间,将附加值累积,即可return,不用向下递归。

key3:Update时,如果不是正好匹配的区间,则将附加值加到当前区间的sum里,这就保证sum保存的是区间[l, r]的和,自然包括附加值,使得查找时可以快速返回。

key4:在Search时,要查找的区间总是包含于当前区间,所以查找过程中遇到的每一个附加值,都要累加起来。

key5:当找到要查找的区间时,也就是正好匹配,return ans + sum即可,ans为key4中累加的值,sum为当前区间的和。

 

ContractedBlock.gif ExpandedBlockStart.gif 代码

   
#include < stdio.h >
#include
< stdlib.h >
#define NN 100000

struct node{
int l, r, cover;
__int64 sum;
__int64 key;
}st[NN
* 8 ];

__int64 f[NN
+ 2 ];

void Init( int l, int r, int id){
st[id].l
= l;
st[id].r
= r;
st[id].cover
= 0 ;
st[id].key
= 0 ;

if (r - l <= 1 ){
st[id].cover
= 1 ;
st[id].sum
= f[l];
return ;
}

int mid = (l + r) >> 1 ;

Init(l, mid, id
* 2 );
Init(mid, r, id
* 2 + 1 );
st[id].sum
= st[id * 2 ].sum + st[id * 2 + 1 ].sum; // key1
}

void Update( int l, int r, __int64 key, int id){

// key2
if (st[id].l == l && st[id].r == r){
st[id].key
+= key;
st[id].cover
= 1 ;
return ;
}
st[id].sum
+= (r - l) * key; // key3
/* if (st[id].cover > 0){
st[id * 2].cover = 1;
st[id * 2 + 1].cover = 1;
st[id * 2].key += st[id].key;
st[id * 2 + 1].key += st[id].key;
st[id].cover = 0;
st[id].key = 0;
}
*/
int mid = (st[id].l + st[id].r) >> 1 ;

if (r <= mid){
Update(l, r, key, id
* 2 );
}
else if (l >= mid){
Update(l, r, key, id
* 2 + 1 );
}
else {
Update(l, mid, key, id
* 2 );
Update(mid, r, key, id
* 2 + 1 );
}
}

__int64 Search(
int l, int r, int id){
__int64 ans
= 0 ;
// key4
if (st[id].cover > 0 ){
ans
+= st[id].key * (r - l);
}

// key5
if (st[id].l == l && st[id].r == r){
ans
+= st[id].sum;
return ans;
}

int mid = (st[id].l + st[id].r) >> 1 ;

if (r <= mid){
return ans + Search(l, r, id * 2 );
}
else if (l >= mid){
return ans + Search(l, r, id * 2 + 1 );
}
else {
return ans + Search(l, mid, id * 2 ) + Search(mid, r, id * 2 + 1 );
}
}
int main()
{
int N, Q, i, a, b;
__int64 c, ans;
char str[ 3 ];
scanf(
" %d%d " , & N, & Q);
for (i = 0 ; i < N; i ++ ){
scanf(
" %I64d " , & f[i]);
}
Init(
0 , N, 1 );
while (Q -- ){
scanf(
" %s " , str);
if (str[ 0 ] == ' Q ' ){
scanf(
" %d%d " , & a, & b);
ans
= Search(a - 1 , b, 1 );
printf(
" %I64d\n " , ans);
}
else {
scanf(
" %d%d%I64d " , & a, & b, & c);
Update(a
- 1 , b, c, 1 );
}
}
// system("pause");
return 0 ;
}

 

代码中我注释了一部分,开始我想错了,想把当前点的key值传到子区间,其实不用,用key2那种方法就行,看来,线段树千变万化,处理技巧很多啊,具体用什么方法,按题而定,学习了,注意总结常用线段树处理方法!

转载于:https://www.cnblogs.com/ylfdrib/archive/2010/07/18/1780070.html

需求响应动态冰蓄冷系统与需求响应策略的优化研究(Matlab代码实现)内容概要:本文围绕“需求响应动态冰蓄冷系统与需求响应策略的优化研究”展开,基于Matlab代码实现,重点探讨了冰蓄冷系统在电力需求响应背景下的动态建模与优化调度策略。研究结合实际电力负荷与电价信号,构建系统能耗模型,利用优化算法对冰蓄冷系统的运行策略进行求解,旨在降低用电成本、平衡电网负荷,并提升能源利用效率。文中还提及该研究为博士论文复现,涉及系统建模、优化算法应用与仿真验证等关键技术环节,配套提供了完整的Matlab代码资源。; 适合人群:具备一定电力系统、能源管理或优化算法基础,从事科研或工程应用的研究生、高校教师及企业研发人员,尤其适合开展需求响应、综合能源系统优化等相关课题研究的人员。; 使用场景及目标:①复现博士论文中的冰蓄冷系统需求响应优化模型;②学习Matlab在能源系统建模与优化中的具体实现方法;③掌握需求响应策略的设计思路与仿真验证流程,服务于科研项目、论文写作或实际工程方案设计。; 阅读建议:建议结合提供的Matlab代码逐模块分析,重点关注系统建模逻辑与优化算法的实现细节,按文档目录顺序系统学习,并尝试调整参数进行仿真对比,以深入理解不同需求响应策略的效果差异。
综合能源系统零碳优化调度研究(Matlab代码实现)内容概要:本文围绕“综合能源系统零碳优化调度研究”,提供了基于Matlab代码实现的完整解决方案,重点探讨了在高比例可再生能源接入背景下,如何通过优化调度实现零碳排放目标。文中涉及多种先进优化算法(如改进遗传算法、粒子群优化、ADMM等)在综合能源系统中的应用,涵盖风光场景生成、储能配置、需求响应、微电网协同调度等多个关键技术环节,并结合具体案例(如压缩空气储能、光热电站、P2G技术等)进行建模与仿真分析,展示了从问题建模、算法设计到结果验证的全流程实现过程。; 适合人群:具备一定电力系统、能源系统或优化理论基础,熟悉Matlab/Simulink编程,从事新能源、智能电网、综合能源系统等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①开展综合能源系统低碳/零碳调度的科研建模与算法开发;②复现高水平期刊(如SCI/EI)论文中的优化模型与仿真结果;③学习如何将智能优化算法(如遗传算法、灰狼优化、ADMM等)应用于实际能源系统调度问题;④掌握Matlab在能源系统仿真与优化中的典型应用方法。; 阅读建议:建议结合文中提供的Matlab代码与网盘资源,边学习理论模型边动手调试程序,重点关注不同优化算法在调度模型中的实现细节与参数设置,同时可扩展应用于自身研究课题中,提升科研效率与模型精度。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值