poj 2796 Feel Good dp || 单调栈
题目链接
题意
对于一个长度为\(n\)的非负整数数列\(a_1,a_2,…,a_n\),求\(max_{1≤l≤r≤n}f(l,r)\), 其中
\]
思路
显然,最小值必为数列中的某个数,所以题目转化为:
对于数列中的 每个数,找 使其 为区间最小值的 最大的区间,即该点向左向右最远能延伸到的地方
// 是不是和那道找最大矩形面积如出一辙?
法一:dp
用\(l[\ ]\)和\(r[\ ]\)记录当前位置向左向右延伸的最远距离。
从左向右计算\(l[\ ]\),计算当前位置的\(l[\ ]\)值时沿着之前计算并记录下来的信息跳着向前找。
\(r[\ ]\)值同理。
法二:单调栈
只需一次遍历,维护一个单调增的栈。
当前栈中每一个元素的右端点至少都是当前位置,左端点则都是之前已记录位置。
踢掉元素进行更新的时候要注意将踢掉元素的左端点的值继承下来,因为踢掉它们意味着它们比当前元素要大,所以当前元素的左端点必然能延伸到它们能延伸到的位置。
由上述过程可看出,当每个元素被踢出来时,其左端点值和右端点值都最终确定了,因而可以计算以它为最小值的这一段对应的答案。
此外,还要注意在最后补上一个最小元素(-1),这是为了保证所有的元素最终都能被踢出来。
说的可能有点抽象...拿样例来说吧
3 1 6 4 5 2
// 以下符号中圆括号中的值代表左端点,方括号中的pair代表左端点和右端点
// 注意:为了看起来直观,下例中栈中的元素均以其对应的值替代,实际操作中真正记录的是下标
*step 1.*
3进栈
3(1)
*step 2.*
踢掉3[1,1],1进栈
1(1)
*step 3.*
6进栈
1(1), 6(3)
*step 4.*
踢掉6[3,3],4进栈
1(1), 4(3)
*step 5.*
5进栈
1(1), 4(3), 5(5)
*step 6.*
踢掉5[5,5],踢掉4[3,5],2进栈
1(1), 2(6)
*step 7.*
踢掉2[6,6],踢掉1[1,6],-1进栈
-1(7)
Code
法一
#include <stdio.h>
#define maxn 100010
using namespace std;
typedef long long LL;
int a[maxn], l[maxn], r[maxn];
LL pre[maxn];
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), pre[i] = pre[i-1] + a[i];
l[1] = 0;
for (int i = 2; i <= n; ++i) {
int p = i-1;
while (p && a[p] >= a[i]) p = l[p];
l[i] = p;
}
r[n] = n+1;
for (int i = n-1; i > 0; --i) {
int p = i+1;
while (p != n+1 && a[p] >= a[i]) p = r[p];
r[i] = p;
}
LL ans = -1;
int ll, rr;
for (int i = 1; i <= n; ++i) {
LL temp = (pre[r[i]-1] - pre[l[i]]) * a[i];
if (temp > ans) ans = temp, ll = l[i]+1, rr = r[i]-1;
}
printf("%lld\n%d %d\n", ans, ll, rr);
return 0;
}
法二
#include <stdio.h>
#include <iostream>
#define maxn 100010
using namespace std;
typedef long long LL;
int a[maxn], st[maxn], l[maxn];
LL pre[maxn];
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
pre[i] = pre[i-1] + a[i];
}
int top = 0;
a[++n] = -1;
LL ans = -1; int lll, rrr;
for (int i = 1; i <= n; ++i) {
int x, ll=i, rr=i-1;
while (top && a[i] < a[st[top-1]]) {
x = st[--top], ll = l[x];
LL temp = a[x] * (pre[rr] - pre[ll-1]);
if (temp > ans) ans = temp, lll = ll, rrr = rr;
}
l[i] = ll; st[top++] = i;
}
printf("%lld\n%d %d\n", ans, lll, rrr);
return 0;
}
后话
既然上面都提到了最大矩形面积...写博客的时候就一时兴起回头翻了翻
hdu 1505 1506 2870 dp小礼包
原来那个时候我就学过一遍单调栈的做法啊...(叹
不管不管现在的代码至少比以前写得好看(
poj 2796 Feel Good dp || 单调栈的更多相关文章
- POJ 2796 Feel Good 【单调栈】
传送门:http://poj.org/problem?id=2796 题意:给你一串数字,需要你求出(某个子区间乘以这段区间中的最小值)所得到的最大值 例子: 6 3 1 6 4 5 2 当L=3,R ...
- POJ 2796 Feel Good(单调栈)
传送门 Description Bill is developing a new mathematical theory for human emotions. His recent investig ...
- Feel Good POJ - 2796 (前缀和+单调栈)(详解)
Bill is developing a new mathematical theory for human emotions. His recent investigations are dedic ...
- 51nod 1215 数组的宽度&poj 2796 Feel Good(单调栈)
单调栈求每个数在哪些区间是最值的经典操作. 把数一个一个丢进单调栈,弹出的时候[st[top-1]+1,i-1]这段区间就是弹出的数为最值的区间. poj2796 弹出的时候更新答案即可 #inclu ...
- POJ 2796:Feel Good 单调栈经典题
Feel Good Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 11626 Accepted: 3212 Case T ...
- POJ 2796:Feel Good 单调栈
题目,给定一个数列,n <= 1e5 .要求找出一个区间,使得其内区间最小值 * 区间总和的值最大,要求输出区间. 首先先维护一个单调递增的栈,同时记录一个lef值表示:lef[i]表示当前栈内 ...
- poj 2769 感觉♂良好 (单调栈)
poj 2769 感觉♂良好 (单调栈) 比尔正在研发一种关于人类情感的新数学理论.他最近致力于研究一个日子的好坏,如何影响人们对某个时期的回忆. 比尔为人的一天赋予了一个正整数值. 比尔称这个值为当 ...
- [luogu]P1169 [ZJOI2007]棋盘制作[DP][单调栈]
[luogu]P1169 [ZJOI]棋盘制作 ——!x^n+y^n=z^n 题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋 ...
- poj 3250 Bad Hair Day (单调栈)
http://poj.org/problem?id=3250 Bad Hair Day Time Limit: 2000MS Memory Limit: 65536K Total Submissi ...
随机推荐
- 搭建Nginx反向代理做内网域名转发
由于公司内网有多台服务器的 http 服务要映射到公司外网静态 IP,如果用路由的端口映射来做,就只能一台内网服务器的 80 端口映射到外网 80 端口,其他服务器的 80 端口只能映射到外网的非 8 ...
- 【JavaScript】修改图片src属性切换图片
今天做项目时其中一个环节需要用到js修改图片src属性切换图片,现在来记录一下 以下是示例: html <img src="/before.jpg" id="img ...
- wcf第三方客户端与wcf服务之间调用入门
Wcf服务与我们的客户端如何建立联系的呢.本文简单记录一下 1.创建我们的wcf服务程序. 第一个wcf服务库是创建我们的wcf库,运行时会单独来托管我们的程序,而非托管在iis下. 第二个wcf服务 ...
- cf984e Elevator
ref我好菜啊 #include <iostream> #include <cstring> #include <cstdio> #include <cmat ...
- Android资源限定符
Android系统会根据设备参数,自动选择最佳资源配置方案. Android中常见的资源限定符: 屏幕特征 限定符 描述 大小 small 提供给小屏幕设备的资源 normal 提供给中等屏幕设备的资 ...
- 【Longest Substring Without Repeating Characters】cpp
题目: Given a string, find the length of the longest substring without repeating characters. For examp ...
- 移动web前端开发小结
注意:Chrome模拟手机的显示的界面是有误差的,强烈建议一定要在真机测试自己的移动端页面(以移动端页面为准). 1.页面高度渲染错误,页面的高度是否包含了导航,(华为手机就是偏偏有底部菜单) 设置窗 ...
- scripts
Shell Script:================================================================ 示例1:[root@server0 ~]# ...
- Leetcode 648.单词替换
单词替换 在英语中,我们有一个叫做 词根(root)的概念,它可以跟着其他一些词组成另一个较长的单词--我们称这个词为 继承词(successor).例如,词根an,跟随着单词 other(其他),可 ...
- Spring七大模块
七大模块,如下: 1. Spring Core: Core封装包是框架的最基础部分,提供IOC和依赖注入特性.这里的基础概念是BeanFactory,它提供对Factory模式的经典实现来消除对程序性 ...