给定一个数组序列, 需要求选出一个区间, 使得该区间是所有区间中经过如下计算的值最大的一个(今日头条笔试第二题)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zzuli_Acmer/article/details/86670486

给定一个数组序列, 需要求选出一个区间, 使得该区间是所有区间中经过如下计算的值最大的一个:

区间中的最小数 * 区间所有数的和最后程序输出经过计算后的最大值即可,不需要输出具体的区间。如给定序列  [6 2 1]则根据上述公式, 可得到所有可以选定各个区间的计算值:

[6] = 6 * 6 = 36;

[2] = 2 * 2 = 4;

[1] = 1 * 1 = 1;

[6,2] = 2 * 8 = 16;

[2,1] = 1 * 3 = 3;

[6, 2, 1] = 1 * 9 = 9;

从上述计算可见选定区间 [6] ,计算值为 36, 则程序输出为 36。

区间内的所有数字都在[0, 100]的范围内;

输入描述:

第一行输入数组序列长度n,第二行输入数组序列。
对于 50%的数据,  1 <= n <= 10000;
对于 100%的数据, 1 <= n <= 500000;

输出描述:

输出数组经过计算后的最大值。

输入例子1:

3
6 2 1

输出例子1:

36

思路一:最开始第一眼看到区间,线段树,两个数组,一个记录最小值,一个记录区间和,但是看到了500000.。。。依然勇敢的码了一发上去(反正随便测。。) 果然只有30%的通过率,贴上代码

#include<bits/stdc++.h>
using namespace std;
#define maxn 500004
int a[maxn],st[maxn];//维护最小值的线段树
int tr[maxn];//维护区间和的线段树
void build(int o,int l,int r)
{
    if( l == r ) st[o] = a[l],tr[o] = a[l];
    else
    {
        int m = (l+r)>>1;
        build(o<<1,l,m);
        build(o<<1|1,m+1,r);
        st[o] = min(st[o<<1],st[o<<1|1]);
        tr[o] = tr[o<<1] + tr[o<<1|1];
    }
}
int query(int L,int R,int l,int r,int o,int k)
{
    if (L<=l&&r<=R)
    {
        if(k == 0)
            return st[o];
        else return tr[o];
    }

    int mid=(l+r)>>1;
    int ans = 0;
    int minn = 999999999;
    if (L<=mid && k == 1) ans+=query(L,R,l,mid,o<<1,1);
    if (R>mid && k == 1) ans+=query(L,R,mid+1,r,o<<1|1,1);
    if (L<=mid && k == 0) minn=min(minn,query(L,R,l,mid,o<<1,0));
    if (R>mid && k == 0) minn=min(minn,query(L,R,mid+1,r,o<<1|1,0));
    if(k == 1)
        return ans;
    else return minn;
}

int main()
{
    int n;
    int maxx = -1;
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
        scanf("%d",&a[i]);
    build(1,1,n);
    for(int i=1; i<=n; i++)
    {
        for(int j=i; j<=n; j++)
        {
            int minn = query(i,j,1,n,1,0);
            int sum = query(i,j,1,n,1,1);
            maxx = max(maxx,minn*sum);
        }
    }
    printf("%d\n",maxx);
}

思路二:看到了所有数据都是在区间[0,100[,因此可以把每个点都当成最小值,然后想左向右寻找边界,也就是第一个小于位置的数,虽然感觉数据应该也很大,但是竟然通过了。。。

#include<bits/stdc++.h>
using namespace std;
#define maxn 500004
int a[maxn];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0; i<n; i++)
        scanf("%d",&a[i]);
    int maxx = -1;

    for(int i=0; i<n; i++)
    {
        //左
        int ans =0 ;
        for(int j=i; j>=0; j--)
        {
            if(a[i]<=a[j])
                ans+=a[j];
            else break;
        }
        //右
        for(int j=i+1; j<n; j++)
        {
            if(a[i]<=a[j])
                ans+=a[j];
            else break;
        }
        maxx = max(maxx,ans*a[i]);
    }
    printf("%d\n",maxx);
    return 0;
}

简单粗暴。。。。

猜你喜欢

转载自blog.csdn.net/zzuli_Acmer/article/details/86670486