这道题可以用ST表过:

题目链接

记录4个数组:maxval[][], minval[][], ans[][], rans[][]

maxval[i][j]表示从i号元素开始,长度为(1<<j)(也就是2^j)的区间上的最大值

minval[i][j]表示从i号元素开始,长度为(1<<j)的区间上的最小值

ans[i][j]表示从i号元素开始,长度为(1<<j)的区间从左往右方向的答案

rans[i][j]表示从i号元素开始,长度为(1<<j)的区间从右往左方向的答案

那么易得如下转移方程:

maxval[i][j] = max(maxval[i][j - 1], maxval[i + (1 << (j - 1))][j - 1])

minval差不多

对于ans和rans的转移,我们这样考虑

区间[l, r]上的答案,要么是区间[l, (l+r)/2]上的答案,要么是区间[(l+r)/2+1, r]上的答案,要么是[(l+r)/2+1, r]上的最大值减去[l, (l+r)/2]上的最小值,以上三者中取最大者

ans[i][j] = max(ans[i][j - 1], ans[i + (1 << (j - 1))][j - 1], maxval[i + (1 << (j - 1))][j - 1] - minval[i][j - 1]);

rans差不多

在预处理的时候,要把j的循环提到外层,因为[l, r]的状态需要用到[(l+r)/2+1, r]的状态转移而来

如果j的循环在内层的话,求解[l, r]的状态时[(l+r)/2+1, r]的状态还没有求解过

查询的过程应该比较好理解,直接看代码吧

#include <algorithm>
#include <cmath>
#include <iostream> using std::cin;
using std::cout;
using std::endl;
using std::max;
using std::min; template <typename T>
inline const T &max(const T &a, const T &b, const T &c)
{
return max(a, max(b, c));
} const double LOG2 = std::log(2);
int a[200010];
int maxval[200010][50];
int minval[200010][50];
int ans[200010][50];
int rans[200010][50];
int n, m; inline void stInit()
{
for (int i = 1; i <= n; ++i)
minval[i][0] = maxval[i][0] = a[i];
for (int j = 1; 1 << j <= n; ++j)
for (int i = 1; i + (1 << j) - 1 <= n; ++i)
{
minval[i][j] = min(minval[i][j - 1], minval[i + (1 << (j - 1))][j - 1]);
maxval[i][j] = max(maxval[i][j - 1], maxval[i + (1 << (j - 1))][j - 1]);
ans[i][j] = max(ans[i][j - 1], ans[i + (1 << (j - 1))][j - 1],
maxval[i + (1 << (j - 1))][j - 1] - minval[i][j - 1]);
rans[i][j] = max(rans[i][j - 1], rans[i + (1 << (j - 1))][j - 1],
maxval[i][j - 1] - minval[i + (1 << (j - 1))][j - 1]);
}
}
inline int queryMax(int l, int r)
{
int k = static_cast<int>(std::log(r - l + 1) / LOG2);
return max(maxval[l][k], maxval[r - (1 << k) + 1][k]);
}
inline int queryMin(int l, int r)
{
int k = static_cast<int>(std::log(r - l + 1) / LOG2);
return min(minval[l][k], minval[r - (1 << k) + 1][k]);
}
inline int queryAns(int l, int r)
{
int k = static_cast<int>(std::log(r - l + 1) / LOG2);
if (l + (1 << k) > r)
return max(ans[l][k], ans[r - (1 << k) + 1][k]);
else
return max(ans[l][k], ans[r - (1 << k) + 1][k],
queryMax(l + (1 << k), r) - queryMin(l, r - (1 << k)));
}
inline int queryRans(int l, int r)
{
int k = static_cast<int>(std::log(r - l + 1) / LOG2);
if (l + (1 << k) > r)
return max(rans[l][k], rans[r - (1 << k) + 1][k]);
else
return max(rans[l][k], rans[r - (1 << k) + 1][k],
queryMax(l, r - (1 << k)) - queryMin(l + (1 << k), r));
} int main()
{
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> a[i];
stInit();
cin >> m;
while (m--)
{
int l, r;
cin >> l >> r;
if (l < r)
cout << queryAns(l, r) << endl;
else if (l > r)
cout << queryRans(r, l) << endl;
else
cout << 0 << endl;
}
return 0;
}

不难看出,查询的时间复杂度是O(1)的,预处理的时间复杂度是O(nlogn)的

最新文章

  1. JSON入门教程
  2. Bootstrap插件系列——Bootstrap-table初始化、分页、客户端搜索、服务端搜索
  3. Transact-SQL 示例 - 使用脚本备份数据库的示例
  4. erp与电子商务集成的结构图
  5. ECshop模板机制
  6. 解决 Provider &#39;System.Data.SqlServerCe.3.5&#39; not installed. -摘自网络
  7. 自己做的网页页面导航浏览JS/JQuery
  8. Can&#39;t connect to local MySQL server through socket
  9. oracle-TNS是什么?
  10. Swift - 给图片添加文字水印(图片上写文字,并可设置位置和样式)
  11. ASP.NET MVC5 视图预编译
  12. LeetCode Javascript实现 258. Add Digits 104. Maximum Depth of Binary Tree 226. Invert Binary Tree
  13. CodeForces - 344E Read Time (模拟题 + 二分法)
  14. 使用eclipse创建web项目的项目图文步骤
  15. postgresql逻辑结构--触发器(三)
  16. params关键字、工具辅助类与、加密与解密
  17. Python 爬虫-Scrapy框架基本使用
  18. jquery datatables api
  19. 终于完成了-- github.com/salomon1184/METP
  20. 机器学习:Mean Shift聚类算法

热门文章

  1. lua require路径设置实例
  2. 第04组 Beta冲刺(1/5)
  3. JavaScript:ES6的新特性
  4. iOS:从头捋一遍VC的生命周期
  5. IT兄弟连 Java语法教程 逻辑运算符
  6. 最全各种系统版本的XPosed框架资料下载整理
  7. SmtpClient发送邮件时附件名称乱码
  8. ASP.NET MVC AJAX 请求中加入 antiforgerytoken 解决“所需的防伪表单字段“__RequestVerificationToken”不存在”问题
  9. Java生鲜电商平台-SpringCloud微服务架构高并发参数优化实战
  10. 史上最全Winform中使用ZedGraph教程与资源汇总整理(附资源下载)