hdu 5696 区间的价值 单调栈+rmq

区间的价值

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Problem Description

我们定义“区间的价值”为一段区间的最大值*最小值。

一个区间左端点在L,右端点在R,那么该区间的长度为(R−L+1)。

现在聪明的杰西想要知道,对于长度为k的区间,最大价值的区间价值是多少。

当然,由于这个问题过于简单。

我们肯定得加强一下。

我们想要知道的是,对于长度为1∼n的区间,最大价值的区间价值分别是多少。

样例解释:

长度为1的最优区间为2−2 答案为6∗6

长度为2的最优区间为4−5 答案为4∗4

长度为3的最优区间为2−4 答案为2∗6

长度为4的最优区间为2−5 答案为2∗6

长度为5的最优区间为1−5 答案为1∗6

Input

多组测试数据

第一行一个数n(1≤n≤100000)。

第二行n个正整数(1≤ai≤109),下标从1开始。

由于某种不可抗力,ai的值将会是1∼109内<b style="color:red;">随机产生</b>的一个数。(除了样例)

Output

输出共n行,第i行表示区间长度为i的区间中最大的区间价值。

Sample Input

5
1 6 2 4 4

Sample Output

36
16
12
12
6

Source

2016"百度之星" - 初赛(Astar Round2B)

思路:利用单调栈得到以a[i]为最小值的区间左端点和右端点;

   发现a[i]*该区间的最大值,为该区间的最小值;

   举个例子;

   5

   1 6 2 4 4

以2为区间最小值,该区间为[2,5];

   在[2,5]区间长度为4,发现在这区间内长度为3,2,1都比2*6=12大;

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 100000007
#define esp 0.00000000001
const int N=1e5+10,M=1e6+10,inf=1e9+10;
ll sum[N<<2];
ll a[N<<2];
int d[N];
int l[N];
int r[N];
ll ans[N];
void build(int l,int r,int pos)
{
    if(l==r)
    {
        sum[pos]=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,pos<<1);
    build(mid+1,r,pos<<1|1);
    sum[pos]=max(sum[pos<<1],sum[pos<<1|1]);
}
ll query(int L,int R,int l,int r,int pos)
{
    if(L<=l&&R>=r)
    return sum[pos];
    int mid=(l+r)>>1;
    ll ans=0;
    if(R>mid)ans=max(ans,query(L,R,mid+1,r,pos<<1|1));
    if(L<=mid)ans=max(ans,query(L,R,l,mid,pos<<1));
    return ans;
}
int main()
{
    int x,y,z,i,t;
    while(~scanf("%d",&x))
    {
        memset(ans,0,sizeof(ans));
        for(i=1;i<=x;i++)
        scanf("%I64d",&a[i]);
        build(1,x,1);
        a[0]=a[x+1]=0;
        int k=0;
        d[++k]=0;
        for(i=1;i<=x;i++)
        {
            while(a[d[k]]>=a[i])k--;
            l[i]=d[k];
            d[++k]=i;
        }
        k=0;
        d[++k]=x+1;
        for(i=x;i>=1;i--)
        {
            while(a[d[k]]>=a[i])k--;
            r[i]=d[k];
            d[++k]=i;
        }
        for(i=1;i<=x;i++)
        ans[r[i]-l[i]-1]=max(ans[r[i]-l[i]-1],(ll)query(l[i]+1,r[i]-1,1,x,1)*a[i]);
        for(i=x-1;i>=1;i--)
        ans[i]=max(ans[i],ans[i+1]);
        for(i=1;i<=x;i++)
        printf("%I64d\n",ans[i]);
    }
    return 0;
}
时间: 2024-08-06 20:06:25

hdu 5696 区间的价值 单调栈+rmq的相关文章

HDU 5696 ——区间的价值——————【线段树、快排思想】

区间的价值 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 662    Accepted Submission(s): 329 Problem Description 我们定义“区间的价值”为一段区间的最大值*最小值. 一个区间左端点在L,右端点在R,那么该区间的长度为(R−L+1). 现在聪明的杰西想要知道,对于长度为k的区间,最大

[hdu] 5696 区间的价值 || 序列分治

原题 我们定义"区间的价值"为一段区间的最大值*最小值. 一个区间左端点在L,右端点在R,那么该区间的长度为(R?L+1). 求长度分别为1-n的区间的最大价值. 保证数据随机 因为保证数据随机,所以我们可以考虑用区间的最大值把这个区间分为两个部分,这样答案的贡献就有两种情况. 1.在同一个区间里 2.跨过最大值,在两个区间里 情况1通过递归就变成了情况2,而情况二我们通过two-points来完成.记录l指针和r指针,因为所求为最大值,所以选取l和r指针较大的内个加入,并每次更新答案

[HDU 5696]区间的价值

[题目]http://acm.hdu.edu.cn/showproblem.php?pid=5696?pid=5696 [题目大意]给一串序列,求区间连续长度为i的最大价值 我一开始打的是N^3的暴力 #include<cstdio> #include<cstring> #include<iostream> #include<vector> #include<queue> #define ll long long #define min(a,b)

hdu 4923 Room and Moor (单调栈+思维)

题意: 给一个0和1组成的序列a,要构造一个同样长度的序列b.b要满足非严格单调,且 值为0到1的实数.最后使得  sum((ai-bi)^2)最小. 算法: 首先a序列开始的连续0和末尾的连续1是可以不考虑的.因为只要b序列对应开头为0. 末尾为1,既不影响单调性又能使对应的(ai-bi)^2=0. 然后, 先找111100.11100.10这样以1开始以0结束的序列块.每一块对应的b值相等且均为 这一块的平均值,即1的个数/0和1的总个数. 但是要满足b的单调性,则我们用栈来维护,如果后面一

POJ2452---Sticks Problem(单调栈+RMQ,方法不够优秀)

Description Xuanxuan has n sticks of different length. One day, she puts all her sticks in a line, represented by S1, S2, S3, -Sn. After measuring the length of each stick Sk (1 <= k <= n), she finds that for some sticks Si and Sj (1<= i < j &

LA 6531 Go up the Ultras 单调栈+RMQ

题意:已经懒得吐槽了..有N个山峰,(N<=10^5),每个山峰有高度h,对应着每个山峰有一个d值,每个山峰到所有其他的严格比 它高的山峰都会经过一个最低值(山谷),d代表是h减去这些最低值中的最大值的差(如果不存在比它高的山峰那么d就是它本身的 高度),问有多少山峰的d>=150000米. 思路:利用单调栈维护每个峰左边第一个比它高的峰的位置l,右边第一个比它高的峰的位置r,对于r,我们从前向后维护一个单调减 序列,如果当前考虑的点i比栈顶的元素高度高,那么弹出栈顶元素,并将它的r置为i,直

【BZOJ4149】[AMPPZ2014]Global Warming 单调栈+RMQ+二分

[BZOJ4149][AMPPZ2014]Global Warming Description 给定一个序列a[1],a[2],...,a[n].请从中选出一段连续子序列,使得该区间最小值唯一.最大值也唯一. 输出选出的子序列的长度的最大值以及取到最大值时左端点的最小值. Input 第一行包含一个正整数n(1<=n<=500000),表示序列长度. 第二行包含n个正整数,依次表示a[1],a[2],...,a[n](-10^9<=a[i]<=10^9). Output 包含一行两

UVALive 6531 Go up the ultras 单调栈+RMQ

题目链接:点击打开链接 题意: 给定n座山 下面n个数字表示n座山的高度 若这座山u合法,则要满足: 1.若u的左边存在比u高的山,设v是u左边距离u最近的且严格比u高的山,在[v,u]之间至少有一座山x,使得x和u的高度差>=15000 2.右边也同理. 同时满足1.2的情况则算合法. 问: 输出所有合法的山. 思路: 求距离某个点最近的山就是维护一个单调栈,然后给山的高度求一个RMQ. 写写写... #pragma comment(linker, "/STACK:1024000000,

HDU 5875 H - Function 用单调栈水过了

单调栈,预处理to[i]表示第一个比a[i]小的数字,一直跳就可以. 这题是数据水而已. 这里学习下单调栈. 构造一个单调递增的栈,并且记录元素大小的同时记录它的id. 每次进来一个小的元素的话,就出栈,同时出栈的这个元素的to[id] = i了,因为这个元素是当时最大的.然后这个a[i]是第一个能让它出栈的,所以就是它了.后面的同理. #include <cstdio> #include <cstdlib> #include <cstring> #include &l