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

Posted Mrha

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[hdu] 5696 区间的价值 || 序列分治相关的知识,希望对你有一定的参考价值。

原题

我们定义“区间的价值”为一段区间的最大值*最小值。
一个区间左端点在L,右端点在R,那么该区间的长度为(R?L+1)。
求长度分别为1~n的区间的最大价值。
保证数据随机


因为保证数据随机,所以我们可以考虑用区间的最大值把这个区间分为两个部分,这样答案的贡献就有两种情况。
1、在同一个区间里
2、跨过最大值,在两个区间里

情况1通过递归就变成了情况2,而情况二我们通过two-points来完成。记录l指针和r指针,因为所求为最大值,所以选取l和r指针较大的内个加入,并每次更新答案即可。
因为数据随机,所以O(nlogn)

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 100010
typedef long long ll;
using namespace std;
ll n,ans[N],a[N];

ll read()
{
    ll ans=0,fu=1;
    char j=getchar();
    for (;(j<'0' || j>'9') && j!='-';j=getchar()) ;
    if (j=='-') j=getchar(),fu=-1;
    for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0';
    return ans*fu;
}

void solve(int l,int r)
{
    if (l>r) return ;
    ll mx=0,pos,mn;
    for (int i=l;i<=r;i++)
    if (a[i]>mx) mx=a[i],pos=i;
    int ll=pos-1,rr=pos+1;
    mn=mx;
    ans[1]=max(ans[1],mx*mx);
    while (ll>=l && rr<=r)
    {
    if (a[ll]<a[rr]) mn=min(a[rr],mn),rr++;
    else mn=min(a[ll],mn),ll--;
    ans[rr-ll-1]=max(ans[rr-ll-1],mx*mn);
    }
    while (ll>=l) mn=min(a[ll],mn),ll--,ans[rr-ll-1]=max(ans[rr-ll-1],mx*mn);
    while (rr<=r) mn=min(a[rr],mn),rr++,ans[rr-ll-1]=max(ans[rr-ll-1],mx*mn);
    solve(l,pos-1);
    solve(pos+1,r);
}

int main()
{
    while (~scanf("%lld",&n))
    {
    memset(ans,0,sizeof(ans));
    for (int i=1;i<=n;i++)
        a[i]=read();
    solve(1,n);
    for (int i=1;i<=n;i++)
        printf("%lld\n",ans[i]);
    }
    return 0;
}

以上是关于[hdu] 5696 区间的价值 || 序列分治的主要内容,如果未能解决你的问题,请参考以下文章

ACM学习历程—HDU5696 区间的价值(分治 && RMQ && 线段树 && 动态规划)

[HDU 5696]区间的价值

hdu5696 区间的价值

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

hdu5696区间的价值 -- 2016"百度之星" - 初赛(Astar Round2B)

Hdu 5696 区间价值(2016百度之星初赛Astar Round2B )(线段树)