51nod 1215 单调栈/迭代
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1215
第1行:1个数N,表示数组的长度。(1 <= N <= 50000)
第2 - N + 1行:每行1个数,表示数组中的元素(1 <= A[i] <= 50000)
输出所有子数组的宽度和。
5
1
2
3
4
5
20
感觉很经典的题目。
首先我们不可能枚举出所有的子区间,显然时空是不允许的,那就要从元素入手,我们只要知道每个元素被作为最大最小值得次数答案就出来了,问题转化为求元素作为最值的次数。
可以找到当前元素作为最大/小值时对应的最大的区间左右端点,然后组合计算一下就是答案了。找这个左右端点时可以用单调栈也可以迭代搜索,stl貌似要慢一些。
正确性在于找端点时满足决策单调性,例如找最大值左端点时,这个元素左侧的元素如果大于他,那显然左端点就是他本身了,此时就是一个单调递减栈,大于栈顶元素时左端点就可以用栈顶
元素的左端点代替;
总之就一句话,大于左侧的元素,一定大于所有左侧元素能大于的元素。
还有就是第一次WA了因为重复计算了, 只要稍微修改一下为左侧不严格右侧严格的查找就好了。
#include <iostream>
#include<algorithm>
#include<stack>
#include<cstdio>
using namespace std;
typedef long long LL;
const int MAX = ;
int a[MAX], l1[MAX], r1[MAX], l2[MAX], r2[MAX];
int maxt[MAX], mint[MAX];
stack<int>S;
int main()
{
int N, i, j, k;
scanf("%d", &N);
for (i = ;i <= N;++i) scanf("%d", a + i);
for (i = ;i <= N;++i)
{
if (S.empty() || a[i] < a[S.top()]) {
l1[i] = i;
S.push(i);
}
else {
while (!S.empty() && a[S.top()] <= a[i]) {
l1[i] = l1[S.top()];
S.pop();
}
S.push(i);
}
}while (!S.empty()) S.pop();
for (i = N;i >=;--i)
{
if (S.empty() || a[i] <= a[S.top()]) {
r1[i] = i;
S.push(i);
}
else {
while (!S.empty() && a[S.top()] < a[i]) {
r1[i] = r1[S.top()];
S.pop();
}
S.push(i);
}
}while (!S.empty()) S.pop();
for (i = ;i <= N;++i)
{
maxt[i] += (r1[i]-l1[i])+(i-l1[i])*(r1[i]-i);
}
for (i = ;i <= N;++i)
{
if (S.empty() || a[i] > a[S.top()]) {
l2[i] = i;
S.push(i);
}
else {
while (!S.empty() && a[S.top()] >=a[i]) {
l2[i] = l2[S.top()];
S.pop();
}
S.push(i);
}
}while (!S.empty()) S.pop();
for (i = N;i>=;--i)
{
if (S.empty() || a[i] >= a[S.top()]) {
r2[i] = i;
S.push(i);
}
else {
while (!S.empty() && a[S.top()] > a[i]) {
r2[i] = r2[S.top()];
S.pop();
}
S.push(i);
}
}while (!S.empty()) S.pop();
for (i = ;i <= N;++i)
{
mint[i] += (-l2[i]+r2[i])+(i-l2[i])*(r2[i]-i);
}
LL ans = ;
for (i = ;i <= N;++i)
{
ans += (LL)a[i] * (maxt[i]-mint[i]);
}
printf("%lld\n", ans);
return ;
}
迭代:
#include <iostream>
#include<algorithm>
#include<stack>
#include<cstdio>
using namespace std;
typedef long long LL;
const int MAX = ;
int a[MAX], l1[MAX], r1[MAX], l2[MAX], r2[MAX];
int maxt[MAX], mint[MAX];
int main()
{
int N, i, j, k;
scanf("%d", &N);
for (i = ;i <= N;++i) scanf("%d", a + i);
for (i = ;i <= N;++i) {
l1[i] = r1[i] = i;
l2[i] = r2[i] = i;
}
for (i = ;i <= N;++i) {
while (l1[i] != && a[i] >= a[l1[i] - ])
l1[i] = l1[l1[i]-];
while (l2[i] != && a[i] <= a[l2[i] - ])
l2[i] = l2[l2[i] - ];
}
for (i = N;i >= ;--i) {
while (r1[i] != N&&a[i] > a[r1[i] + ])
r1[i] = r1[r1[i] + ];
while (r2[i] != N&&a[i] < a[r2[i] + ])
r2[i] = r2[r2[i] + ];
}
LL ans = ;
for (i = ;i <= N;++i) {
ans += (LL)a[i] * ((r1[i] - l1[i]) + (i - l1[i])*(r1[i] - i)- (-l2[i] + r2[i]) - (i - l2[i])*(r2[i] - i));
}
cout << ans << endl;
//system("pause");
return ;
}
51nod 1215 单调栈/迭代的更多相关文章
- 51nod 1102 单调栈
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1102 1102 面积最大的矩形 基准时间限制:1 秒 空间限制:1310 ...
- 51nod 1279 单调栈
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1279 1279 扔盘子 题目来源: Codility 基准时间限制:1 ...
- 51nod 1215 数组的宽度&poj 2796 Feel Good(单调栈)
单调栈求每个数在哪些区间是最值的经典操作. 把数一个一个丢进单调栈,弹出的时候[st[top-1]+1,i-1]这段区间就是弹出的数为最值的区间. poj2796 弹出的时候更新答案即可 #inclu ...
- 51nod 1437 迈克步(单调栈)
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1437 题意: 思路: 单调栈题.求出以每个数为区间最大值的区间范围即可. ...
- 51nod 1102 面积最大的矩形 (单调栈)
链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1102 思路: 首先介绍下单调栈的功能:利用单调栈,可以找到从左/ ...
- 51nod 1102 面积最大的矩形(单调栈)
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1102 题意: 思路: 做法就是求出每个长方形向左向右所能延伸的最大距离. ...
- 51Nod 1158 全是1的最大子矩阵 —— 预处理 + 暴力枚举 or 单调栈
题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1158 1158 全是1的最大子矩阵 基准时间限制:1 秒 空 ...
- 51nod 1158 全是1的最大子矩阵(单调栈 ,o(n*m))
前置问题:51nod 1102 面积最大的矩形 附上链接: 51nod 1102 面积最大的矩形 这题的题解博客 需要了解的知识:单调栈,在前置问题中已经讲解. 解题思路 对每行求左边连续1的个数,得 ...
- [多校联考2019(Round 4 T2)][51nod 1288]汽油补给(ST表+单调栈)
[51nod 1288]汽油补给(ST表+单调栈) 题面 有(N+1)个城市,0是起点N是终点,开车从0 -> 1 - > 2...... -> N,车每走1个单位距离消耗1个单位的 ...
随机推荐
- PAT 1069. 微博转发抽奖(20)
小明PAT考了满分,高兴之余决定发起微博转发抽奖活动,从转发的网友中按顺序每隔N个人就发出一个红包.请你编写程序帮助他确定中奖名单. 输入格式: 输入第一行给出三个正整数M(<= 1000).N ...
- 设计一个算法,採用BFS方式输出图G中从顶点u到v的最短路径(不带权的无向连通图G採用邻接表存储)
思想:图G是不带权的无向连通图.一条边的长度计为1,因此,求带顶点u和顶点v的最短的路径即求顶点u和顶点v的边数最少的顶点序列.利用广度优先遍历算法,从u出发进行广度遍历,类似于从顶点u出发一层一层地 ...
- make编译三
多目标 Makefile 的规则中的目标可以不止一个,其支持多目标,有可能我们的多个目标同时依赖于一个文件,并且其生成的命令大体类似.于是我们就能把其合并起来.但是如果多个目标的生成规则的执行命令是同 ...
- myBatis 课纲
myBatis 课纲 第一章 MyBatis 架构.主要构件及相互关系 使用 MyBatis 构建项目 基本的增删改查映射文件方式(特殊符号处理),使用接口方式实现 结果集映射: 单个对象映射到Has ...
- JavaWeb—Servlet
1.什么是Servlet 用来扩展web服务器功能的组件——早期的web服务器只能处理静态资源的请求,即需要事先将html文件准备好,并存放到web服务器上面.不能够处理动态资源的请求(需要计算,动态 ...
- python 里安装 tensorflow 后运行出错的问题解决
如果出现一下错误: libcublas.so.8.0: cannot open shared object file: No such file or directory 原因是没有 cuda 环境, ...
- python并发编程之多进程2-(数据共享及进程池和回调函数)
一.数据共享 1.进程间的通信应该尽量避免共享数据的方式 2.进程间的数据是独立的,可以借助队列或管道实现通信,二者都是基于消息传递的. 虽然进程间数据独立,但可以用过Manager实现数据共享,事实 ...
- Android 结束进程的方法forceStopPackage
ActivityManager sd = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE); Method method = Clas ...
- 快乐学习 Ionic Framework+PhoneGap 手册1-4 {登录页面}
编程的快乐和乐趣,来自于能成功运行程序并运用到项目中 有了面板然后加个登录页面,请看效果图和代码 Index HTML Code <!DOCTYPE html> <html ng-a ...
- Python字符串格式转换
转换类型 转换类型 说明 d, i 带符号十进制 b 无符号二进制 o 无符号八进制 u 无符号十进制 x 无符号十六进制(小写) X 无符号十六进制(大写) e 科学计数法表示的浮点数(小写) E ...