更新:之前的写法那么挫居然也过了。。。缝缝改改最后从1.4S改成700ms了。。。主要改的地方是两处 ,见注释
修改后的代码放在最后面(700ms)
最后重xie(400ms)
题意:给一个数组,求任意区间的最大连续和 长度n,查询次数m n,m大小是5*10^5
每个数不超过1e9
之前做的是静态数组求一次最大连续和,方法有很多,dp之类的都能o(n)解决。
还有一个是分治法,nlogn解决:http://blog.csdn.net/viphong/article/details/48221429
这里也是用分治法的思路解决:
称区间【l,r】的最大连续区间和为st_max[l,r]
对查询区间(a,b)
int mid=(a+b)/2;
要求st_max的话, 有三种情况:
情况1: st_max的起点和终点都在【a,mid】
情况2:st_max的起点和终点都在【mid+1,b】
情况3:st_max的起点在【a,mid】,终点在【mid+1,b】
对于情况三 : st_max= max_suffix(a,mid)+max_prefix(mid+1,b) 【容易理解】
其中max_suffix为一区间的最大后缀和
其中max_prefix为一区间的最大前缀和
所以,任意区间的st_max 都可求得。只要不断递归下去就可以了。 【线段树维护区间的结果】
而对于max_suffix、max_prefix,我们也是用分治的方法来求
例如 要求max_prefix【a,b】
那么先求max_prefix【a,mid】和max_prefix【mid+1,b】
然后选 max_prefix【a,mid】 和max_prefix【mid+1,b】+sum[mid] 中 较大的一个 即为 【a,b】的最大前缀和,其中sum【i】为前缀和数组
同理也可以分治求得max_suffix
-------------------------------------------------
最终是 用 两个线段树分别维护 max_prefix、max_suffix
再用一棵线段树维护最大连续和
建树nlogn
每次查询logn...常数应该比较大....所以跑了1.4S。。。犇都是0.x秒
1、要注意的是inf不能设为2^63-1 会溢出
2、维护某个最大连续和对应的始末位置 我是另创了一个node来记录
3、在情况三下,用query_max查找最大前/后缀和的时候,
查询的l,应该是当前区间的l和要查询的区间的l中 较大的一个
查询的r,应该是当前区间的r和要查询的区间的r中 较小的一个
重写了一次代码。。
#include
#include
#include
#include
#include
#include
#include
#include