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个单位的 ...
随机推荐
- 常用算法及其Python实现
冒泡排序 def bubble_sort(li): for i in range(len(li)-1): # i表示第几趟 for j in range(len(li)-i-1 ...
- Python lxml 使用
lxml,是python中用来处理xml和html的功能最丰富和易用的库 from lxml import etree from lxml import html h = ''' <html&g ...
- 010-spring事务管理
一.Spring的事务传播行为 事务是从哪里传播到哪里? 是从方法A传播至方法B. Spring事务类型详解: PROPAGATION_REQUIRED--如果当前没有事务,就新建一个事务.如果有,就 ...
- OpenCV3计算机视觉+python(三)
使用OpenCV3处理图像 下面要介绍的内容都与图像处理有关,这时需要修改图像,比如要使用具有艺术性的滤镜.外插(extrapolate)某些部分.分割.粘贴或其他需要的操作. 不同色彩空间的转换 O ...
- [转载]分布式session处理方案
伴随网站业务规模和访问量的逐步发展,原本由单台服务器.单个域名的迷你网站架构已经无法满足发展需要. 此时我们可能会购买更多服务器,并且启用多个二级子域名以频道化的方式,根据业务功能将网站分布部署在独立 ...
- HDU 1159 Common Subsequence(POJ 1458)
Common Subsequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- (C#)ListView双击Item事件
/// <summary> /// 双击选择播放列表项进行播放 /// </summary> /// <param name="sender"> ...
- 深入浅出Node.js(上)
(一):什么是Node.js Node.js从2009年诞生至今,已经发展了两年有余,其成长的速度有目共睹.从在github的访问量超过Rails,到去年底Node.jsS创始人Ryan Dalh加盟 ...
- xml转换为对象 微信接口
public sealed class XMLSerilizable { /// <summary> /// XML转换为对象 /// </summary> /// <t ...
- java基础—— Collections.sort的两种用法
package com.jabberchina.test; import java.util.ArrayList; import java.util.Collections; import java. ...