百度之星初赛B hdu5696 区间的价值 分治思想

来源:互联网 发布:php 字符串true false 编辑:程序博客网 时间:2024/06/13 04:32
突然在做这个题目的时候,想到高中数学老师,那句经典的口头禅
"两个数的我不做,我只会做一个数"^_^!

分治的思想:
    首先题目要求的是“区间的价值”为一段区间的最大值*最小值,对于长度为1∼n的区间,最大价值的区间价值分别是多少

想法如下:
    如果在这个区间里我先固定了最小值,也就是先去确定最小值是多少,然后我去计算以最小值为中心,左右两边的区间价值,然后我就可以更新整个区间的最大价值然后二分调用solve(l,p-1)和solve(p+1,r)这两个区间里最小值然后确定每一个区间段的最大值再去更新整个区间的最大价值!
solve(l,r)来求出区间[l,r]中各种区间长度的最大价值。

随着区间变长,如果最小值是固定的,那么最大值只有可能越来越大,价值才会越来越大

题解报告给出了单调栈的一种解决办法,待我做完之后再更新!

代码:

/*    */#include<iostream>#include<cstdio>#include<cstring>#define LL long longusing namespace std;const int MAXN = 1e5+5;LL a[MAXN],temp[MAXN],ans[MAXN];void solve(int l,int r){    if(l>r)        return ;    int p=0;    for(int i = l;i<=r;i++)    {        if(!p||a[i]<a[p])            p = i;    }    int w = r-l+1;    for(int i = 1;i<=w;i++)        temp[i] = 0;    LL pre = 0;    //遍历一遍区间获得他们的最大区间值    for(int i = p-1;i>=l;i--)    {        if(temp[p-i+1]<max(pre,(LL)a[p]*a[i]))        {            temp[p-i+1] = max(pre,(LL)a[p]*a[i]);            //因为最小值固定下来了,也就是看最大值哪个大            //短区间的值可以给长区间做更新(也就是短区间的最大值更大)            pre=temp[p-i+1];        }    }    pre = 0;    for(int i = p+1;i<=r;i++)    {        if(temp[i-p+1]<max(pre,(LL)a[p]*a[i]))        {            temp[i-p+1] = max(pre,(LL)a[p]*a[i]);            pre = temp[i-p+1];        }    }    ans[1] = max(ans[1],a[p]*a[p]);    pre = 0;    //整体的区间长度的最大价值更新操作    for(int i = 2;i<=w;i++)    {        if(ans[i]<max(pre,temp[i]))        {            ans[i]=max(pre,temp[i]);        }        pre = max(pre,temp[i]);    }    solve(l,p-1);    solve(p+1,r);}int main(){    freopen("in2.txt","r",stdin);    //freopen("out1.txt","w",stdout);    int n;    while(~scanf("%d",&n))    {        memset(ans,0,sizeof(ans));        for(int i = 0;i<MAXN;i++)            temp[i] = 0;        for(int i =1;i<=n;i++)            scanf("%I64d",&a[i]);        solve(1,n);        for(int i = 1;i<=n;i++)        {            printf("%I64d\n",ans[i]);        }    }    return 0;}


   
0 0
原创粉丝点击