题目链接:https://vjudge.net/contest/146667#problem/C

题意:动态的求一个区间的最大连续和。

分析:

看上去可以RMQ去做,但是,当分成两个部分,原来的部分的解可能是跨越这两个区间的。原问题的解不能通过RMQ分成的两个部分的解而得到。

线段树:

线段树很早之前就有学习,那个时候只会套模板,而这个题目几乎就是线段树的一个理解应用。

就在刚刚之前提到的那个问题一样,可以利用线段树维护3个信息:

max_prefix(最大前缀和的标号)

max_suffix(最大后缀和的标号)

有了这两个信息,就可以跨区间找到丢失的信息了。

还有一个就是结果 max_sub(最大连续和的标号,其中是一个pair类型)

建树时:

建好左右子树后,递推max_prefix,max_suffix,这两个都不用跨区间,递推max_sub需要跨区间。

这里没有更新操作。

询问时:

同样分三种情况,左半边,右半边,跨区间。

跨区间这里,就用到了我们之前维护的最大前缀和标号,和最大后缀和标号。

那么如何得到最大前缀和标号,和最大后缀和标号呢?

同理:也是分区间查找,但是右半部分的左边的标号必须是L,左半部分简单一点,就是左孩子的最大前缀和的标号。

同理最大后缀和的标号。

 #include <bits/stdc++.h>

 using namespace std;

 const int maxn =  + ;
const int maxnode = + ;
typedef long long LL;
typedef pair<int,int> Interval; LL prefix_sum[maxn]; //求区间和
LL sum(int L,int R) {
return prefix_sum[R] - prefix_sum[L-];
} //求区间和
LL sum(Interval p) {
return sum(p.first,p.second);
} Interval better(Interval a,Interval b) {
if(sum(a)!=sum(b)) return sum(a) > sum(b) ? a : b;
return a<b? a:b;
} int qL,qR; struct IntervalTree
{
int max_prefix[maxnode]; //最大前缀和对应的标号
int max_suffix[maxnode]; //最大后缀和对应的标号
Interval max_sub[maxnode]; //最大连续和对应的起点和终点 void build(int o,int L,int R)
{
if(L==R)
{
max_prefix[o] = max_suffix[o] = L;
max_sub[o] = make_pair(L,L);
}
else
{
int M = L+(R-L)/;
int lc = o*,rc = o*+;
build(lc,L,M);
build(rc,M+,R); //递推最大前缀和
LL v1 = sum(L,max_prefix[lc]);
LL v2 = sum(L,max_prefix[rc]);
if(v1==v2) max_prefix[o] = min(max_prefix[lc],max_prefix[rc]);
else max_prefix[o] = v1 > v2 ? max_prefix[lc] : max_prefix[rc]; //递推最大后缀和
v1 = sum(max_suffix[lc],R);
v2 = sum(max_suffix[rc],R);
if(v1==v2) max_suffix[o] = min(max_suffix[lc],max_suffix[rc]);
else max_suffix[o] = v1 > v2 ? max_suffix[lc] : max_suffix[rc]; //递推最大连续和
max_sub[o] = better(max_sub[lc],max_sub[rc]);
max_sub[o] = better(max_sub[o],make_pair(max_suffix[lc],max_prefix[rc]));
}
} //求最大前缀和的那个区间
Interval query_prefix(int o,int L,int R)
{
if(max_prefix[o]<=qR) return make_pair(L,max_prefix[o]);
int M = L + (R-L)/;
int lc = o*,rc = o* + ;
if(qR<=M) return query_prefix(lc,L,M);
Interval i = query_prefix(rc,M+,R);
i.first = L;
return better(i,make_pair(L,max_prefix[lc]));
} Interval query_suffix(int o,int L,int R)
{
if(max_suffix[o]>=qL) return make_pair(max_suffix[o],R);
int M = L + (R-L) /;
int lc = o*,rc = o*+;
if(qL>M) return query_suffix(rc,M+,R);
Interval i = query_suffix(lc,L,M);
i.second = R;
return better(i,make_pair(max_suffix[rc],R)); } Interval query(int o,int L,int R)
{
if(qL<=L&&R<=qR) return max_sub[o];
int M = L + (R - L) /;
int lc = o*,rc = o*+;
if(qR<=M) return query(lc,L,M);
if(qL>M) return query(rc,M+,R);
Interval i1 = query_prefix(rc,M+,R);
Interval i2 = query_suffix(lc,L,M);
Interval i3 = better(query(lc,L,M),query(rc,M+,R)); //分开
return better(make_pair(i2.first,i1.second),i3); //跨区间
} }; IntervalTree tree; int main()
{
int n,q,a;
int cases = ;
while(scanf("%d%d",&n,&q)==)
{
prefix_sum[] = ;
for(int i=; i<n; i++)
{
scanf("%d",&a);
prefix_sum[i+] = prefix_sum[i] + a;
}
tree.build(,,n);
printf("Case %d:\n",cases++); while(q--) {
int L,R;
scanf("%d%d",&L,&R);
qL = L;
qR = R;
Interval ans = tree.query(,,n);
printf("%d %d\n",ans.first,ans.second);
} } return ;
}

LA 3938 动态最大连续和的更多相关文章

  1. LA 3938 动态最大连续和 线段树

    题目链接: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show ...

  2. LA 3938 动态最大连续和(线段树)

    https://vjudge.net/problem/UVALive-3938 题意:给出一个长度为n的整数序列D,你的任务是对m个询问作出回答.对于询问(a,b),需要找到两个下标x和y,使得a≤x ...

  3. LA 3938 动态最大连续区间 线段树

    思路很清晰,实现很繁琐.分析过程可以参考LRJ,自己的总结晚些放. #include <cstdio> #include <cstring> #include <algo ...

  4. UVALive 3938 Ray, Pass me the dishes! (动态最大连续和)

    题意:求一个动态区间的最大连续和. 静态版本的O(n)算法显示不适用了,但是可以用线段树分治,因为一个连续和要在两边的区间,要么跨越两边,对于一个结点维护最大前缀和,后缀和,子区间连续和. 题目要求输 ...

  5. 2018年1月 mybatis+ 动态sql连续日期

    2018-01-111 .   如何在项目中快速查找对应的mapper.xml文件 从Controller入手,使用(Ctrl+鼠标左键)找到Service调用的方法,再找到底层方法,就能找到对应ma ...

  6. la 3938(未完成)

    题意:给出一个长度为n的整数序列D,你的任务是对m个询问作出回答.对于询问(a,b), 需要找到两个下标x和y,使得a≤x≤y≤b,并且Dx+Dx+1+...+Dy尽量大. 如果有多组满足条件的x和y ...

  7. 一个动态库连续注册的windows脚本regsvr32

    cmd ->for %1 in (%windir%\system32\*.dll) do regsvr32.exe /s %1

  8. LA 3938

    After doing Ray a great favor to collect sticks for Ray, Poor Neal becomes very hungry. In return fo ...

  9. 线段树(区间合并) LA 3989 "Ray, Pass me the dishes!"

    题目传送门 题意:动态最大连续子序列和,静态的题目 分析:nlogn的归并思想.线段树维护结点的三个信息,最大前缀和,最大后缀和,该区间的最大和的两个端点,然后答案是三个的better.书上用pair ...

随机推荐

  1. 解决报错:import sun.misc.BASE64Decoder无法找到

    解决报错:import sun.misc.BASE64Decoder无法找到 2017年09月29日 16:03:26 chaoyu168 阅读数:2116 标签: sun.misc.BASE64De ...

  2. Lucene.Net和盘古分词应用

    Lucene.Net.dll:用做全文索引 PanGu.dll(盘古分词):作为中文分词的条件 大致原理: 1.Lucene先根据PanGu将需要搜索的内容分隔.分词,然后根据分词的结果,做一个索引页 ...

  3. spring boot 系统启动时运行代码(1)-@PostConstruct

    Application.java import org.springframework.boot.SpringApplication; import org.springframework.boot. ...

  4. 约瑟夫环问题poj1012

    题意: 有k个坏人k个好人坐成一圈,前k个为好人(编号1~k),后k个为坏人(编号k+1~2k) 现在有一个报数m,从编号为1的人开始报数,报到m的人就要自动死去. 问当m为什么值时,可以使得在出现好 ...

  5. 苏D_8M150

    20161226 麦德龙 西边 弄堂 前车 转弯 刹车,我 刹车,下雨路滑,滑到.没撞到前车.车型号没看...只记了车牌... 右手撑了一下,肩膀估计是撑伤了,举起来 比较疼... 不知 该如何处理, ...

  6. jQuery自动完成插件flexselect

    项目中使用flexselect自动完成插件时遇到一个问题 刚开始以为是js的引用顺序有问题,但是查看后发现不是js引用顺序问题 js引用顺序如下 最后查找资料也没有解决问题,一直提示这个错误 后来在f ...

  7. Win2003 控制面板 打不开

    windown 2003 控制面板打不开 在运行框中输入regedit,进入注册表中的 HKEY_LOCAL_MACHINE/SYSTEM\Current ControlSet\Control\NLS ...

  8. Big Data Opportunities and Challenges(by周志华)论文要点

    大数据环境下的机器学习 三种误解:模型不再重要(大量数据上复杂模型依然提升显著,大数据是的复杂模型充分利用数据且难以过拟合),相关性就足够了(因果关系重要性无法被替代),以前的研究方向不再重要(高性能 ...

  9. javascript判断input框只能输入数字的方法

    javascript 只允许输入数字有很多方法,总结如下 1,只允许输入数字和小数点. <input onKeypress="return (/[\d.]/.test(String.f ...

  10. The function getUserId must be used with a prefix when a default namespace is not specified 解决办法

    The function getUserId must be used with a prefix when a default namespace is not specified 解决方法: 1. ...