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个单位的 ...
随机推荐
- myBatis 课纲
myBatis 课纲 第一章 MyBatis 架构.主要构件及相互关系 使用 MyBatis 构建项目 基本的增删改查映射文件方式(特殊符号处理),使用接口方式实现 结果集映射: 单个对象映射到Has ...
- 剑指offer 面试53题
面试53题: 题目:统计一个数字在排序数组中出现的次数. 思路:二分查找法,分别找到此数字在排序数组中第一次和最后一次出现的位置,然后次数等于两个位置之差加1. 时间复杂度:O(log n) 解题代码 ...
- Autonomous System
自治系统(Autonomous System).在互联网中,一个自治系统(AS)是一个有权自主地决定在本系统中应采用何种路由协 议的小型单位.这个网络单位可以是一个简单的网络也可以是一个由一个 ...
- 对称加密&非对称加密
对称密钥密码算法的特点: 算法简单,加/解密速度快,但密钥管理复杂,不便于数字签名: 非对称密钥密码算法的特点: 算法复杂,加/解密速度慢,密钥管理简单,可用于数字签名. 所以将两者结合起来,形成混合 ...
- 20160418 while,switch,do..while的使用
9 一.While循环 示例:求100以内所有数的和 Int i=1;//初始条件 Int sum=0; While(i<=100)//循环条件 { Sum+=i;//循环体 i++;//状态改 ...
- php异常处理类
<?php header('content-type:text/html;charset=UTF-8'); // 创建email异常处理类 class emailException extend ...
- C# Invoke 使用 异步委托
如果使用多线程,应该会遇到这样的一个问题,在子线程中想调用主线程中(Form1)控件,提示报错! 可以使用Invoke方法调用. this.Invoke(new MethodInvoker(() =& ...
- javascript;json数据,js转换日期方法。
接收json数据,日期格式为:"\/Date(1414078309687)\/" var value = "/Date(1414078309687)/"; va ...
- Python学习进程(10)字典
本节介绍Python中的字典:是另一种可变容器模型,且可存储任意类型对象. (1)字典简介: 字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割 ...
- layer满屏/禁止最大化最小化 可以做选择框使用
1.layer弹窗最大化 var index=layer.open(); layer.full(index); 2.layer禁止最大化最小化 layer.open( [ type:2, title: ...