uvalive 3938 "Ray, Pass me the dishes!" 线段树 区间合并
题意:求q次询问的静态区间连续最大和起始位置和终止位置 输出字典序最小的解.
思路:刘汝佳白书 每个节点维护三个值
pre, sub, suf 最大的前缀和, 连续和, 后缀和 然后这个题还要记录解的位置所以还要区间总和sum
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define ll long long
#define clc(a,b) memset(a,b,sizeof(a)) 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; // 利用pair自带的字典序
} 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); // 递推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], 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 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 ;
}
uvalive 3938 "Ray, Pass me the dishes!" 线段树 区间合并的更多相关文章
- UVALive 3938 - "Ray, Pass me the dishes!" - [最大连续子列和+线段树]
题目链接:https://cn.vjudge.net/problem/UVALive-3938 参考刘汝佳书上说的: 题意: 给出一个长度为n的序列, 再给出m个询问, 每个询问是在序列 $[a,b] ...
- UVALive 3938 Ray, Pass me the dishes! (动态最大连续和)
题意:求一个动态区间的最大连续和. 静态版本的O(n)算法显示不适用了,但是可以用线段树分治,因为一个连续和要在两边的区间,要么跨越两边,对于一个结点维护最大前缀和,后缀和,子区间连续和. 题目要求输 ...
- UVA 1400."Ray, Pass me the dishes!" -分治+线段树区间合并(常规操作+维护端点)并输出最优的区间的左右端点-(洛谷 小白逛公园 升级版)
"Ray, Pass me the dishes!" UVA - 1400 题意就是线段树区间子段最大和,线段树区间合并,但是这道题还要求输出最大和的子段的左右端点.要求字典序最小 ...
- POJ 3667 Hotel(线段树 区间合并)
Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...
- HDU 3911 线段树区间合并、异或取反操作
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...
- HDU 3911 Black And White(线段树区间合并+lazy操作)
开始以为是水题,结果...... 给你一些只有两种颜色的石头,0为白色,1为黑色. 然后两个操作: 1 l r 将[ l , r ]内的颜色取反 0 l r 计算[ l , r ]内最长连续黑色石头的 ...
- HYSBZ 1858 线段树 区间合并
//Accepted 14560 KB 1532 ms //线段树 区间合并 /* 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[ ...
- poj3667 线段树 区间合并
//Accepted 3728 KB 1079 ms //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...
- hdu3911 线段树 区间合并
//Accepted 3911 750MS 9872K //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...
随机推荐
- 【原创】一起学C++ 之 字符串 ---------C++ primer plus(第6版)
C++ Primer Plus 第6版 字符串:是存储在内存的连续字节中的一系列字符. C++处理字符串的方式有2种: 一.来自C语言.常被称为C-风格字符串(C-Style-string) 1)从字 ...
- hdu 3944 DP? 组合数取模(Lucas定理+预处理+帕斯卡公式优化)
DP? Problem Description Figure 1 shows the Yang Hui Triangle. We number the row from top to bottom 0 ...
- AWR报告导出的过程报ORA-06550异常
刚才在笔记本上(win 7)想要导出一套RAC的AWR报告(linux),执行awrgrpt.sql的脚本的过程中报错了,报错的异常代码是:ORA-06550.经过检查,发现是用户的问题,换成sys用 ...
- Spring核心框架 - AOP之动态代理机制
动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码.动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类. ...
- DB天气app冲刺第七天
今天估计得分应该是最差的了. 今天因为完全没准备所以在界面UI上面根本就是相当于没弄.结果今天的各组报告里自己做得很不好.不过好在只是项目的中间期,不碍大事. 今天也完成了任务.可以说超额了也.因为吃 ...
- C#.net winform 控件和皮肤大全
1. 东日IrisSkin IrisSkin 共有两个版本,一个是IrisSkin.dll 用于.Net Framework1.0/1.1 和IrisSkin2.dll 用于.Net Framewor ...
- hex(x) 将整数x转换为16进制字符串
>>> a = 122 >>> b = 344 >>> c = hex(a) >>> d = hex(b) >>&g ...
- UIWebView 与 JS 交互(1):Objective-C 调用 Javascript
众所周知,随着硬件水平的发展,HTML5 与原生 APP 性能差距不断缩小,正在互联网科技领域扮演者越来越重要的角色.作为一种能很大程度上节约成本的技术方案,通过 HTML5 及 JS 实现的跨平台技 ...
- OpenStack项目列表
这个也是必须要熟悉的哟. ~~~~~~~~~~ OpenStack是一个美国国家航空航天局和Rackspace合作研发的,以Apache许可证授权,并且是一个自由软件和开放源代码项目.OpenStac ...
- POJ - 1523 SPF
题目要求割顶集,并且还要求出去掉割顶之后剩下的图连通数目. tarjan算法求出割顶后直接枚举就可以了吧. 一开始想到利用iscut[u]的次数也就是点u被判定为割顶的次数求连通分量数,还有利用与结点 ...