[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;
}
时间: 2024-11-09 10:50:01

[hdu] 5696 区间的价值 || 序列分治的相关文章

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

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]区间的价值

[题目]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)

1674 区间的价值 V2(分治)

1674 区间的价值 V2 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 lyk拥有一个区间. 它规定一个区间的价值为这个区间中所有数and起来的值与这个区间所有数or起来的值的乘积. 例如3个数2,3,6.它们and起来的值为2,or起来的值为7,这个区间对答案的贡献为2*7=14. 现在lyk有一个n个数的序列,它想知道所有n*(n+1)/2个区间的贡献的和对1000000007取模后的结果是多少. 例如当这个序列为{3,4,5}时,那么区间[1,1],

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

思路来源于:http://blog.csdn.net/kk303/article/details/51479423 注意数组用 long long 存,否则WA. /* Problem : Status : By wf, */ #include "algorithm" #include "iostream" #include "cstring" #include "cstdio" #include "string&q

51nod1674:区间的价值2(分治,利用&amp;和|的收敛性)

lyk拥有一个区间. 它规定一个区间的价值为这个区间中所有数and起来的值与这个区间所有数or起来的值的乘积. 例如3个数2,3,6.它们and起来的值为2,or起来的值为7,这个区间对答案的贡献为2*7=14. 现在lyk有一个n个数的序列,它想知道所有n*(n+1)/2个区间的贡献的和对1000000007取模后的结果是多少. 例如当这个序列为{3,4,5}时,那么区间1,11,1,1,21,2,1,31,3,2,22,2,2,32,3,3,33,3的贡献分别为9,0,0,16,20,25.

51nod 1674 区间的价值V2(思维+拆位+尺取法)

最近被四区题暴虐... 题意:lyk拥有一个区间. 它规定一个区间的价值为这个区间中所有数and起来的值与这个区间所有数or起来的值的乘积. 例如3个数2,3,6.它们and起来的值为2,or起来的值为7,这个区间对答案的贡献为2*7=14. 现在lyk有一个n个数的序列,它想知道所有n*(n+1)/2个区间的贡献的和对1000000007取模后的结果是多少. 区间的and值和区间的or值相乘,实际上等于将and值分解为2的幂次和的形式与or值分解成2的幂次和的形式相乘. 所以对于同一段区间来说

HDU5696 区间的价值

传送门 一道比较基础的分治题--但是我似乎不会分治-- 首先,区间的价值肯定与最小值有关,所以对于当前处理的区间,我们首先暴力的求出区间的最小值,其位置记为pos.之后--对于一个横跨过pos的区间,它的价值必定可以由pos左右两边区间的价值更新而来,所以说我们只需要暴力的在左右两边O(n)的扫一遍求出相应的长度的区间价值最大值,之后用较短的区间的价值更新较长的即可. 之后再递归分治pos的左右两边的区间即可. 本题的关键在于,能通过找到pos这个位置,之后把横跨过pos的区间的值由左右两边更新

区间的价值(线段树)百度之星

区间的价值 Accepts: 0 Submissions: 0 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Description 我们定义“区间的价值”为一段区间的最大值*最小值. 一个区间左端点在LLL,右端点在RRR,那么该区间的长度为(R−L+1)(R-L+1)(R−L+1). 现在聪明的杰西想要知道,对于长度为kkk的区间,最大价值的区间价值是多少.