题目链接: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. my16_sql_thread执行慢导致主从延迟高的一个情景

    现象:从库延迟高,查看slave status发现sql_thread执行语句的速度比主库慢,这样的延迟会一直高下去,下面是排查的一些过程1. 检查了从库的配置,磁盘的写入速度的确没有主库高2. io ...

  2. 关于WampServer一些配置修改

    1.解决WAMP mysql中文乱码问题(在mysql的my.ini文件中) 1).找到client字段并添加:default-character-set=utf8 2).找到mysql字段并添加: ...

  3. 使用Koa.js,离不开这十个中间件

    随着ES6的普及,async/await的语法受到更多JS开发者的青睐,Koa.js作为比较早支持使用该语法的Node框架越来越受到大家的喜爱,虽然Koa.js本身支持的功能很有限,但官方和社区提供了 ...

  4. chrome浏览器解决 跨域调试问题

    1.关闭chrome浏览器(全部) 我们可以通过使用chrome命令行启动参数来改变chrome浏览器的设置,具体的启动参数说明参考这篇介绍.https://code.google.com/p/xia ...

  5. tomcat异常[1]--java.lang.ClassNotFoundException: XXXX.EncodingFilter

    EncodingFilter类在java项目中,确实存在,但是启动项目时,总是说找不到这个类. 后来想了一下,项目运行取的应该是项目WEB-INF/classes下面已经编译为.class文件的类文件 ...

  6. execlp启动android进程命令

    execlp启动Android界面或service/广播参数设置 -n代表打开组件-d代表 data-a代表action 打开网页 调用am命令 if (sdkVersion >= 17) { ...

  7. maya 安装失败

    AUTODESK系列软件着实令人头疼,安装失败之后不能完全卸载!!!(比如maya,cad,3dsmax等).有时手动删除注册表重装之后还是会出现各种问题,每个版本的C++Runtime和.NET f ...

  8. ubuntu安装软件依赖解决

    sudo apt-get install -f zsh@zsh:~/Downloads/dist$ sudo dpkg --install Kitematic_0.17.3_amd64.deb (正在 ...

  9. jquery dataTable 自定义 Button及按钮事件

    参考网址:http://stackoverflow.com/questions/18134913/jquery-datatabletabletool-custom-buttons-calling-ev ...

  10. .NET标准化题目

    1. 下面对FxCop的描述中,错误的是:(D) A. FxCop是一个静态代码分析工具. B. 可以定制自己的规则加入FxCop引擎. C. FxCop主要是对.NET中托管代码的assembly进 ...