求一个区间的最大连续子序列,基本想法就是分治,这段子序列可能在区间的左半边,也可能在区间的右半边,也有可能是横跨区间中点,这样就是左子区间的最大后缀加上右子区间的最大前缀之和。

线段树维护三个信息:区间最大前缀、最大后缀、最大连续子区间的下标。

最大前缀可以通过递推来求:要么是左子区间的最大前缀和、要么是左子区间的和 加上 右子区间的最大前缀和

最大后缀和的递推类似。

递推之前要预处理整个序列的前缀和。

 #include <cstdio>
#include <cstring>
#include <algorithm>
#define MP make_pair
#define lch(o) (o*2)
#define rch(o) (o*2+1)
using namespace std; typedef long long LL;
typedef pair<int, int> Interval;
const int maxn = + ;
const int maxnode = + ; LL prefix_sum[maxn]; LL sum(int a, int b) { return prefix_sum[b] - prefix_sum[a-]; } 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; //pair自带字典序
} int qL, qR; //查询区间 struct IntervalTree
{
int max_prefix[maxnode], 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] = MP(L, L); }
else
{
int M = (L + R) >> ;
int lc = lch(o), rc = rch(o);
build(lc, L, M);
build(rc, M+, R); //递推max_prefix
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]; //递推max_suffix
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
max_sub[o] = better(max_sub[lc], max_sub[rc]);
max_sub[o] = better(max_sub[o], MP(max_suffix[lc], max_prefix[rc]));
}
} Interval query_prefix(int o, int L, int R)
{
if(max_prefix[o] <= qR) return MP(L, max_prefix[o]);
int M = (L + R) >> ;
int lc = lch(o), rc = rch(o);
if(qR <= M) return query_prefix(lc, L, M);
Interval i = query_prefix(rc, M+, R);
i.first = L;
return better(i, MP(L, max_prefix[lc]));
} Interval query_suffix(int o, int L, int R)
{
if(max_suffix[o] >= qL) return MP(max_suffix[o], R);
int M = (L + R) >> ;
int lc = lch(o), rc = rch(o);
if(qL > M) return query_suffix(rc, M+, R);
Interval i = query_suffix(lc, L, M);
i.second = R;
return better(i, MP(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) >> ;
int lc = lch(o), rc = rch(o);
if(qR <= M) return query(lc, L, M);
if(qL > M) return query(rc, M+, R);
Interval i1 = query_suffix(lc, L, M);//左子区间的最大后缀
Interval i2 = query_prefix(rc, M+, R);//右子区间的最大前缀
Interval i3 = better(query(lc, L, M), query(rc, M+, R));//两个子区间的最大连续和
return better(i3, MP(i1.first, i2.second));
}
}tree; int main()
{
//freopen("in.txt", "r", stdin); int kase = , n, a, Q;
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", ++kase);
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 ;
}

代码君

UVa 1400 (线段树) "Ray, Pass me the dishes!"的更多相关文章

  1. UVA 1400 线段树

    input n m 1<=n,m<=500000 a1 a2 ... an |ai|<=1e9 m行查询 每行一对a b output 对于每对a b输出区间[a,b]中最小连续和x ...

  2. UVA 1400."Ray, Pass me the dishes!" -分治+线段树区间合并(常规操作+维护端点)并输出最优的区间的左右端点-(洛谷 小白逛公园 升级版)

    "Ray, Pass me the dishes!" UVA - 1400 题意就是线段树区间子段最大和,线段树区间合并,但是这道题还要求输出最大和的子段的左右端点.要求字典序最小 ...

  3. UVA 1400 1400 - &quot;Ray, Pass me the dishes!&quot;(线段树)

    UVA 1400 - "Ray, Pass me the dishes!" option=com_onlinejudge&Itemid=8&page=show_pr ...

  4. UvaLA 3938 "Ray, Pass me the dishes!"

                            "Ray, Pass me the dishes!" Time Limit: 3000MS   Memory Limit: Unkn ...

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

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

  6. uva 1400 - "Ray, Pass me the dishes!"

    又是一道线段树区间更新的题: #include<cstdio> #include<algorithm> #include<cstring> #define ll l ...

  7. UVALive 3938 - "Ray, Pass me the dishes!" - [最大连续子列和+线段树]

    题目链接:https://cn.vjudge.net/problem/UVALive-3938 参考刘汝佳书上说的: 题意: 给出一个长度为n的序列, 再给出m个询问, 每个询问是在序列 $[a,b] ...

  8. uva 11525(线段树)

    题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  9. UVA 11297 线段树套线段树(二维线段树)

    题目大意: 就是在二维的空间内进行单个的修改,或者进行整块矩形区域的最大最小值查询 二维线段树树,要注意的是第一维上不是叶子形成的第二维线段树和叶子形成的第二维线段树要  不同的处理方式,非叶子形成的 ...

随机推荐

  1. .NET开源项目介绍及资源推荐:数据持久层

    在.NET平台下,关于数据持久层框架非常多,本文主要对如下几种做简要的介绍并推荐一些学习的资源: 1.NHibernate 2.NBear 3.Castle ActiveRecord 4.iBATIS ...

  2. js 正则 数值验证

    function checkTextDataForNORMAL(strValue) { // 特殊字符验证格式 var regTextChar = /([\*"\'<>\/])+ ...

  3. 【转,未试】android 9path教程与去黑边

      本帖最后由 ArcherFMY 于 2013-4-24 17:39 编辑 <ignore_js_op> draw9patch.zip (124.83 KB) 这是Draw9patch& ...

  4. [sql server、oracle] 分组取最大值最小值常用sql

    sqlserver2005前: --分组取最大最小常用sql--测试环境if OBJECT_ID('tb') is not null drop table tb;gocreate table tb(  ...

  5. UVA 11858 Frosh Week 逆序对统计

    题目链接: http://acm.hust.edu.cn/vjudge/contest/122094#problem/H Frosh Week Time Limit:8000MSMemory Limi ...

  6. apache nginx php不显示版本号

    apache 不显示版本号 http.conf 中的 修改为 ServerTokens ProdServerSignature Off 有的版本没有,在最后添加即可 php php.ini 中的 修改 ...

  7. Unit Test Generator

           

  8. 检测php网站是否已经被攻破的方法

    0x01 查看访问日志 看是否有文件上传操作(POST方法), IPREMOVED - - [01/Mar/2013:06:16:48 -0600] "POST/uploads/monthl ...

  9. OneAPM 技术公开课第二讲:开启性能为王的架构时代

    「OneAPM 技术公开课」由应用性能管理第一品牌 OneAPM 发起,内容面向 IT 开发和运维人员.云集技术牛人.知名架构师.实践专家共同探讨技术热点.继北京站第一场火爆上演之后,第二场将于9月1 ...

  10. POJ 2246 Matrix Chain Multiplication(结构体+栈+模拟+矩阵相乘)

    题意:给出矩阵相乘的表达式,让你计算需要的相乘次数,如果不能相乘,则输出error. 思路: 参考的网站连接:http://blog.csdn.net/wangjian8006/article/det ...