[POJ2796]Feel Good

  题目传送门:http://poj.org/problem?id=2796

  这道题的话我用了RMQ和二分。

  思想:用minm来表示区间[L,R]的最小值,很明显一个区间[L,R]能取得的最大值,要么就是[L,minm-1],要么就是[minm+1,R],还有就是整个区间的和乘最小值。

  因为对于某两个最小值相等的区间来说(题目说明是非负整数),显然越大的区间取得的最大值越大。

    

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=100010;
int num[maxn],n,sum[maxn],fmin[maxn][20],fmax[maxn][20];
long long ans=0,ansl,ansr;

int querymin(int l,int r)
{
    int k=0;
    if (l>r)return 0;
    while (1<<(k+1)<=r-l+1)k++;
    return min(fmin[l][k],fmin[r-(1<<k)+1][k]);
}

int querymax(int l,int r)
{
    int k=0,tmp=0;
    if (l>r)return 0;
    while (1<<(k+1)<=r-l+1)k++;
    tmp=max(fmax[l][k],fmax[r-(1<<k)+1][k]);
    tmp=max(tmp,(sum[r]-sum[l-1])*querymin(l,r));
    if (tmp>ans)
    {
       ans=tmp;
       ansl=l;
       ansr=r;
    }
    return tmp;
}

void findmin()                                          //用RMQ求第i个到第j个这个区间的最小值是哪一个
{
     int i,j;
     memset(fmin,0x7f,sizeof(fmin));
     for (i=1;i<=n;i++)fmin[i][0]=i;
     for (j=1;(1<<j)<=n;j++)
         for (i=1;i+(1<<j)-1<=n;i++)
             if (num[fmin[i][j-1]]<num[fmin[i+(1<<(j-1))][j-1]])fmin[i][j]=fmin[i][j-1];
                else fmin[i][j]=fmin[i+(1<<(j-1))][j-1]; 
}

void findmax()                                           //表示求第i个到第j个这个区间能取得的最大值
{
     int i,j,l,r;
     memset(fmax,0,sizeof(fmax));
     for (i=1;i<=n;i++)fmax[i][0]=num[i]*num[i];
     for (j=1;(1<<j)<=n;j++)
         for (i=1;i+(1<<j)-1<=n;i++)
         {
             r=i+(1<<j)-1;
             l=querymin(i,r);
             fmax[i][j]=max(querymax(i,max(i,l-1)),querymax(max(l+1,r),r));
             fmax[i][j]=max(fmax[i][j],(sum[r]-sum[i-1])*num[l]);
             if (fmax[i][j]>ans)
             {
                ans=fmax[i][j];
                ansl=i;
                ansr=r;
             }
         }
}

int main()
{
    int i,j;
    scanf("%d",&n);
    sum[0]=0;
    for (i=1;i<=n;i++)
    {
        scanf("%d",&num[i]);
        sum[i]=sum[i-1]+num[i];
    }
    findmin();
    findmax();
    cout<<ans<<endl<<ansl<<" "<<ansr<<endl;
    return 0;
}

 

posted @ 2016-03-02 22:46  Sun_Sea  阅读(181)  评论(0编辑  收藏  举报