POJ2796 Feel Good -- 单调队列

                          

                                Feel Good

Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 14489   Accepted: 4015
Case Time Limit: 1000MS   Special Judge

Description

Bill is developing a new mathematical theory for human emotions. His recent investigations are dedicated to studying how good or bad days influent people‘s memories about some period of life.

A new idea Bill has recently developed assigns a non-negative integer value to each day of human life.

Bill calls this value the emotional value of the day. The greater the emotional value is, the better the daywas. Bill suggests that the value of some period of human life is proportional to the sum of the emotional values of the days in the given period, multiplied by the smallest emotional value of the day in it. This schema reflects that good on average period can be greatly spoiled by one very bad day.

Now Bill is planning to investigate his own life and find the period of his life that had the greatest value. Help him to do so.

Input

The first line of the input contains n - the number of days of Bill‘s life he is planning to investigate(1 <= n <= 100 000). The rest of the file contains n integer numbers a1, a2, ... an ranging from 0 to 106 - the emotional values of the days. Numbers are separated by spaces and/or line breaks.

Output

Print the greatest value of some period of Bill‘s life in the first line. And on the second line print two numbers l and r such that the period from l-th to r-th day of Bill‘s life(inclusive) has the greatest possible value. If there are multiple periods with the greatest possible value,then print any one of them.

Sample Input

6
3 1 6 4 5 2

Sample Output

60
3 5

题意:  给出一个数列,求其一个区间中 最小值 与 区间元素和 的成绩的最大值;分析:  1.将每个元素看做所在区间的最小值 向左右两区间进行查找,找以其为最小值的最大区间;  2.单调队列的应用,以查找以当前元素为最小值的最大区间的左端点为例:    ①构造严格递增的单调队列,即进队元素需比队尾元素大,否则队尾元素出队;   ②从第一个元素开始进行进队,将当前值与队尾进行比较,若队尾大于当前元素,则队尾出队,否则队尾元素的下标便是以当前元素为最小值    的最大区间的左端点;     查找以当前元素为最小值的最大区间的右端点方法相同。代码分析:
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <vector>
 7 #include <map>
 8 #include<string.h>
 9 #include<stack>
10 #include<set>
11 #include <queue>
12 using namespace std;
13
14 long long a[100005];
15 //数组模拟队列
16 long long q[100005];
17 //以每个元素为最小值的最大区间左端点
18 long long l[100005];
19 //以每个元素为最小值的最大区间右端点
20 long long r[100005];
21 //存队列中每个元素的下标
22 long long p[100005];
23 //区间的值
24 long long sum[100005];
25 int main()
26 {
27     int n,i,j;
28     while(~scanf("%d",&n))
29     {
30         sum[0] = 0;
31         for(i = 1; i<=n; i++)
32         {
33             scanf("%lld",a+i);
34             sum[i] = sum[i-1]+a[i];
35         }
36         //初始化队头
37         q[0] = -1;
38         p[0] = 0;
39         p[n+1] = n+1;
40         q[n+1] = -1;
41         int head = 1;
42         int tail = 0;
43         //查找以当前元素为最小值的最大区间的左端点
44         for(i = 1 ; i<=n; i++)
45         {
46
47             while(head<=tail&&q[tail]>=a[i]) tail--;//队尾元素大于等于当前元素
48             //以当前元素为最小值的最大区间的左端点
49             l[i] = p[tail];
50             //当前元素进队
51             q[++tail] = a[i];
52             //记录下标
53             p[tail] =  i;
54         }
55         //查找以当前元素为最小值的最大区间的右端点
56         q[0] = -1;
57         p[0] = 0;
58         p[n+1] = n+1;
59         q[n+1] = -1;
60         head = n;
61         tail = n+1;
62         for(i = n ; i>=1; i--)
63         {
64             while(head>=tail&&q[tail]>=a[i]) tail++;
65             r[i] = p[tail];
66             q[--tail] = a[i];
67             p[tail] =  i;
68         }
69         long long max1 = -1;
70         int k = 0;  //标记最大值的区间
71         for(i = 1; i<=n; i++)
72         {
73
74          if(max1<a[i]*(sum[r[i]-1]-sum[l[i]]))
75          {
76              max1= a[i]*(sum[r[i]-1]-sum[l[i]]);
77              k = i;
78          }
79         }
80         printf("%lld\n",max1);
81         printf("%lld %lld\n",l[k]+1,r[k]-1);
82
83     }
84     return 0;
85 }

个人随笔,望大佬勿喷,若能提供帮助不胜荣幸。

时间: 2024-08-03 23:20:27

POJ2796 Feel Good -- 单调队列的相关文章

【动态规划】【单调队列】tyvj1305 最大子序和

http://blog.csdn.net/oiljt12138/article/details/51174560 单调队列优化dp #include<cstdio> #include<deque> #include<algorithm> #include<iostream> using namespace std; typedef long long ll; int n,m; ll a[300100],ans; deque<int>q; int

hdu_5884_Sort(二分+单调队列)

题目链接:hdu_5884_Sort 题意: 有n个数,每个数有个值,现在你可以选择每次K个数合并,合并的消耗为这K个数的权值和,问在合并为只有1个数的时候,总消耗不超过T的情况下,最小的K是多少 题解: 首先要选满足条件的最小K,肯定会想到二分. 然后是如何来写这个check函数的问题 我们要贪心做到使消耗最小,首先我们将所有的数排序 然后对于每次的check的mid都取最小的mid个数来合并,然后把新产生的数扔进优先队列,直到最后只剩一个数. 不过这样的做法是n*(logn)2 ,常数写的小

[Vijos 1243]生产产品(单调队列优化Dp)

Description 在经过一段时间的经营后,dd_engi的OI商店不满足于从别的供货商那里购买产品放上货架,而要开始自己生产产品了!产品的生产需要M个步骤,每一个步骤都可以在N台机器中的任何一台完成,但生产的步骤必须严格按顺序执行.由于这N台机器的性能不同,它们完成每一个步骤的所需时间也不同.机器i完成第j个步骤的时间为T[i,j].把半成品从一台机器上搬到另一台机器上也需要一定的时间K.同时,为了保证安全和产品的质量,每台机器最多只能连续完成产品的L个步骤.也就是说,如果有一台机器连续完

单调队列

先放上luogu的题目链接--滑稽窗口 然后我们再来讲单调队列 单调队列是指这样一种队列:在队列中的元素为单调递增状态或单调递减状态. 例如1 2 3 4 5和9 2 1都是单调队列,但1 2 2 3 4和4 3 4 5就不是单调队列. 但普通队列明显是维持不了单调队列的性质的. 为了维持单调队列的单调性质,我们只好想一些方法.方法就是修改队列的性质.单调队列不仅队头可以出队,队尾也可以出队. 比如说有一个单调队列是 1 3 7 8 现在突然要从队尾进来一个6如果单纯的把6插进队尾的话,那这个队

单调队列 BZOJ 2096 [Poi2010]Pilots

2096: [Poi2010]Pilots Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 819  Solved: 418[Submit][Status][Discuss] Description Tz又耍畸形了!!他要当飞行员,他拿到了一个飞行员测试难度序列,他设定了一个难度差的最大值,在序列中他想找到一个最长的子串,任意两个难度差不会超过他设定的最大值.耍畸形一个人是不行的,于是他找到了你. Input 输入:第一行两个有空格隔开的整数k(0

HDU 3706 Second My Problem First (单调队列)

题意:求给定的一个序列中最长子序列,该子序列的最大值和最小值介于m和k之间. 析:用两个单调队列来维护一个最小值,一个最大值,然后每次更新即可. 代码如下; #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <i

codevs3327选择数字(单调队列优化)

3327 选择数字 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 给定一行n个非负整数a[1]..a[n].现在你可以选择其中若干个数,但不能有超过k个连续的数字被选择.你的任务是使得选出的数字的和最大. 输入描述 Input Description 第一行两个整数n,k 以下n行,每行一个整数表示a[i]. 输出描述 Output Description 输出一个值表示答案. 样例输入 Sample Input 5 2

【NOIP数据结构专项】单调队列单调栈

[洛谷P1901 ]发射站 http://www.luogu.org/problem/show?pid=1901 题目描述 某地有 N 个能量发射站排成一行,每个发射站 i 都有不相同的高度 Hi,并能向两边(当 然两端的只能向一边)同时发射能量值为 Vi 的能量,并且发出的能量只被两边最近的且比 它高的发射站接收. 显然,每个发射站发来的能量有可能被 0 或 1 或 2 个其他发射站所接受,特别是为了安 全,每个发射站接收到的能量总和是我们很关心的问题.由于数据很多,现只需要你帮忙计 算出接收

【单调队列优化DP】BZOJ1855-[Scoi2010]股票交易

[题目大意] 已知第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=BPi),第i天的一次买入至多只能购买ASi股,一次卖出至多只能卖出BSi股. 股票交易所规定在两次交易(某一天的买入或者卖出均算是一次交易)之间,至少要间隔W天,也就是说如果在第i天发生了交易,那么从第i+1天到第i+W天,均不能发生交易.同时,在任何时间,一个人的手里的股票数不能超过MaxP. 在第1天之前,有一大笔钱(可以认为钱的数目无限),没有任何股票,求T天之后最多赚到多