单调栈poj2796
题意:给你一段区间,需要你求出(在这段区间之类的最小值*这段区间所有元素之和)的最大值......
例如:
6
3 1 6 4 5 2
以4为最小值,向左右延伸,6 4 5 值为60.......
思路:解决完为这道题目,我才真正明白了单调栈的原理,它就是以某一个值为最小(最大)值,向这个值的两侧延伸,遇到大于它(小于它)的值,就将它延伸的范围扩大,当然,一般来说,要这样做的算法复杂度为o(n^2),但是借助栈这个玩意,维护其单调增(减),就可以在o(n)的时间复杂度解决这个问题。将一元素加入栈时,先判断它是否大于(小于)栈顶元素,若是大于(小于)栈顶元素,加入栈。(从这里开始只讲维护单调增栈)否则,将栈顶元素出栈,直到栈顶元素小于要加入栈的元素,在此过程中,需要维护向前延伸和向后延伸的问题,当要加入栈的元素之前有n个栈元素出栈,那么说明这n个出栈的元素都会大于或者等于要入栈的元素,此时,我们需要维护入栈元素可以向前延伸多少个元素(相当于记录它的前面有多少个元素比它大),而每个栈顶元素要向出栈了的元素延伸,因为在出栈了的元素一定是比它的大的元素(根据我维护的是单调增栈)......这样,就在o(n)的时间复杂度内解决了上述问题.........
例如:3 1 6 4 5 2
(3,1,1) (1,2,2) (6,3,3) (4,4,4) (5,5,5) (2,6,6)
首先每个元素自己本身的前后延伸都为1,把3加入栈,1<3,把3出栈,用1的前延伸加上3的前延伸,如此变为(1,1,2),6<1,入栈,变成(1,1,2)(6,3,3),
4<6,将6出栈,4向前延伸,1向后延伸变成(1,1,3) (4,3,4)
5>4,入栈,变成(1,1,3)(4,3,4)(5,5,5)
2<5,5出栈,2向前延伸,4向后延伸,变成(1,1,3)(4,3,5) 2还未入栈(2,5,6)
2<4,4出栈,2向前延伸,1向后延伸,变成(1,1,5) (2,3,6).....
一次类推,会发现最大的结果在(4,3,5)这里这意味着,以4为最小值的区间范围为3————5,也就是6 4 5
#include<iostream>
#include<stack>
#include<stdio.h>
using namespace std;
#define maxx 110000
__int64 str[maxx],t[maxx];
struct node
{
__int64 num,pre,next; //num记录数值,pre记录向前延伸多少个,next记录向后延伸多少个,k记录本身所处的位置
__int64 k;
};
int main()
{
int n;
while(scanf("%d",&n)>0)
{
stack<node>Q;
node tmp;
__int64 ans=-100,sum=-100,num;
str[0]=0;
for(__int64 i=1;i<=n;i++)
{
scanf("%I64d",&t[i]);
if(i==1)
str[i]=t[i];
else
str[i]=str[i-1]+t[i];
}
tmp.num=t[1];
tmp.pre=1;
tmp.next=1;
tmp.k=1;
Q.push(tmp);
__int64 x=0,y=0;
for(__int64 i=2;i<=n;i++)
{
node tmp1;
tmp1.num=t[i];
tmp1.pre=tmp1.next=1;
tmp1.k=i;
while(!Q.empty()&&tmp1.num<=Q.top().num)
{
tmp=Q.top();
Q.pop();
if(!Q.empty())
Q.top().next+=tmp.next;
tmp1.pre+=tmp.pre;
ans=tmp.num*(str[tmp.k+tmp.next-1]-str[tmp.k-tmp.pre]);
if(ans>=sum)
{
sum=ans;
x=tmp.k-tmp.pre+1;
y=tmp.k+tmp.next-1;
}
}
Q.push(tmp1);
}
while(!Q.empty())
{
tmp=Q.top();
Q.pop();
if(!Q.empty())
Q.top().next+=tmp.next;
ans=tmp.num*(str[tmp.k+tmp.next-1]-str[tmp.k-tmp.pre]);
if(ans>=sum)
{
sum=ans;
x=tmp.k-tmp.pre+1;
y=tmp.k+tmp.next-1;
}
} if(n==0)x=y=0;
printf("%I64d\n%I64d %I64d\n",sum,x,y);
}
return 0;
}
单调栈poj2796的更多相关文章
- POJ2796 Feel Good 单调栈
题意:给定一个序列,需要找出某个子序列S使得Min(a[i])*Σa[i] (i属于S序列)最大 正解:单调栈 这题的暴力还是很好想的,只需3分钟的事就可以码完,以每个点拓展即可,但这样的复杂度是O( ...
- upc组队赛1 小C的数学问题【单调栈】(POJ2796)
小C的数学问题 题目描述 小C是个云南中医学院的大一新生,在某个星期二,他的高数老师扔给了他一个问题. 让他在1天的时间内给出答案. 但是小C不会这问题,现在他来请教你. 请你帮他解决这个问题. 有n ...
- poj2796 维护区间栈//单调栈
http://poj.org/problem?id=2796 题意:给你一段区间,需要你求出(在这段区间之类的最小值*这段区间所有元素之和)的最大值...... 例如: 6 3 1 6 4 5 2 以 ...
- POJ2796(单调栈)
Feel Good Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 12987 Accepted: 3639 Case T ...
- 【POJ2796】Feel Good 单调栈
题目大意:给定一个长度为 N 的序列,求任意区间 [ l , r ] 中最小的\(min\{v[i],i\in[l,r] \}*\Sigma_{i=l}^rv[i]\). 题解:这是一道具有标准单调栈 ...
- POJ2796 Feel Good(单调栈)
题意:给一个非负整数序列,求哪一段区间的权值最大,区间的权值=区间所有数的和×区间最小的数. 用单调非递减栈在O(n)计算出序列每个数作为最小值能向左和向右延伸到的位置,然后O(n)枚举每个数利用前缀 ...
- UVA 1619/POJ2796 滑窗算法/维护一个单调栈
Feel Good Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 12409 Accepted: 3484 Case T ...
- POJ2796【单调栈】
题意: 题意:n个数,求某段区间的最小值*该段区间所有元素之和的最大值 思路: 主要参考:http://www.cnblogs.com/ziyi–caolu/archive/2013/06/23/31 ...
- POJ2796Feel Good[单调栈]
Feel Good Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 13376 Accepted: 3719 Case T ...
随机推荐
- js 中三层引号问题
方式1: '[{"Company": "XYZ","Description": "\"TEST\"" ...
- ViewFlipper 淘宝头条 轮播 自动切换
ViewFlipper介绍 ViewFilpper类继承于ViewAnimator,而ViewAnimator类继承于FrameLayout. ViewAnimator: Base class ...
- 线程本地存储TLS(Thread Local Storage)的原理和实现——分类和原理
本文为线程本地存储TLS系列之分类和原理. 一.TLS简述和分类 我们知道在一个进程中,所有线程是共享同一个地址空间的.所以,如果一个变量是全局的或者是静态的,那么所有线程访问的是同一份,如果某一个线 ...
- angularjs中ng-repeat的使用
第一个例子:使用ng-repeat最简单的例子 <html ng-app="myApp"> <head> <title>angularjs-de ...
- 流操作结束后,一定要调用close(). java有垃圾回收器, 这样做是多此一举吗?
流不单在内存中分配了空间,也在操作系统占有了资源, java的gc是能从内存中回收不使用的对象, 但对操作系统分配的资源是无能为力的, 所以就要调用close()方法来通知OS来释放这个资源.
- Array.prototype.slice.call 和 slice以及call
单独的简单介绍,后续再补上一些资料. 对象转换为数组. /** * slice : 数组->slice(截取) * 参数有两个,开始截取和结束截取,并返回原数组: * a.slice(1) || ...
- 关于Javascript表单验证
//验证字符串非空 var Validator = { VerityLib: { IsNotEmpty: function (input) { if ...
- 如何使用T-SQL备份还原数据库及c#如何调用执行? C#中索引器的作用和实现。 jquery控制元素的隐藏和显示的几种方法。 localStorage、sessionStorage用法总结 在AspNetCore中扩展Log系列 - 介绍开源类库的使用(一) span<T>之高性能字符串操作实测
如何使用T-SQL备份还原数据库及c#如何调用执行? 准备材料:Microsoft SQL Server一部.需要还原的bak文件一只 一.备份 数据库备份语句:user master backup ...
- 摘:C/C++中时间类time.h
摘要:本文从介绍基础概念入手,探讨了在C/C++中对日期和时间操作所用到的数据结构和函数,并对计时.时间的获取.时间的计算和显示格式等方面进行了阐述.本文还通过大量的实例向你展示了time.h头文件中 ...
- 使用多字节字符集的跨平台(PC、Android、IOS、WP)编码/解码方法
随着移动端的发展,跨平台已成为通讯架构设计的重要考虑因素,PC.Android.IOS.WP等跨多平台间的数据通讯,必然要解决字符编码/解码的问题. 多字节字符集MBCS不是跨平台的首选字符集,面向跨 ...