「EZEC-5」人赢

在这里插入图片描述
在这里插入图片描述
输入:
样例1
3
3 2 1

样例2
5
3 4 5 4 3

输出:
样例1
6

样例2
28

思路: 核心:贪心 / 单调栈

首先分析题意,找最大值,尽可能让k * (x+y)大。
对于x==y ,我们可以在输入数据时候,枚举特判掉。
剩下x!=y的情况,不妨设 kx < ky,对于kx来说y的k值已经没用了,k * ( x+y)中k和x已经定了,剩下让y尽可能让下标大一点。

法一:排序 + 贪心 O(nlogn)
先按k值从大到小排序,把k值大的先作为x(默认kx<ky),因为k越大可以选择的y越少(因为选的y要满足 ky > kx ),枚举满足的y就好了,然后一边更新答案,一边更新y的最大值。
说是枚举y,其实只要保留最大下标y即可。

法二:单调栈维护k O(n)
ps:此题有加强版,只能用O(n)
边输入边存,因为是顺序输入,所以后来者的下标肯定越大,放在栈顶,单调递减栈维护ky值从小到大,栈顶ky小于当前的kx,所以kx的最大y(即最大下标在栈顶取,因为顺序输入)。
具体维护单调栈的操作如下:
设已读的元素为y,未读或者正在读的元素为x,当kx < ky时,直接入栈,更新答案,当kx ≥ ky时,一边更新答案,一边将 ky ≤ kx 的元素退栈,最后一次退栈后,还要和栈内的元素再维护一下最大值。

法一:贪心+排序

//贪心
#include<bits/stdc++.h>
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
using namespace std;
typedef long long ll;
const int N=1e6+10;

struct ty
{
    
    
    int id;//下标
    int k;//权值
}a[N];
bool cmp(ty a,ty b)//按照k值排序
{
    
    
    if( a.k!= b.k ) return a.k>b.k;
    return a.id > b.id;
}
int main()
{
    
    
    int n;
    ll ans=0;
    scanf("%d",&n);

    _for(i,1,n)
    {
    
    
    scanf("%d", &a[i].k);
    a[i].id = i;
    ans = max( ans, 1ll * a[i].k * i);
    }
    sort( a+1 ,a+1+n, cmp);
    int maxn=0;//最大下标
    for(int i=1 ;i<=n ;i++)
    {
    
    
        //更新答案
        ans = max(ans ,1ll * (a[i].id + maxn) * a[i].k );
        maxn = max( maxn, a[i].id );//维护最大下标
    }
    printf("%lld\n",ans);
    return 0;
}

法二:单调栈

//单调栈
#include<bits/stdc++.h>
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
using namespace std;

typedef long long ll;
const int N=1e6+10;

int a[N];
vector <int> st[2]; //0值 1下标
int main()
{
    
    
    int n;
    ll ans=0;
    scanf("%d",&n);

    _for(i,1,n)
    {
    
    
    scanf("%d", &a[i]);
    ans = max( ans, 1ll * a[i] * i);
    }
    //单调栈维护k
    //栈顶下标必定最大,栈里维护k递减且栈顶k小于当前k
    _for(i,1,n)
    {
    
    
        while(  !st[0].empty() && a[i]>=st[0].back() )
        {
    
    
            int x = st[0].back();
            int y = st[1].back();
            ans = max( ans ,1ll* x * (y+i) );
            st[0].pop_back();
            st[1].pop_back();
        }

        if( !st[0].empty())
        {
    
    
            int x = st[0].back();
            int y = st[1].back();
            ans = max( ans ,1ll* a[i] * (y+i) );
        }
        st[0].push_back(a[i]);
        st[1].push_back(i);
    }
    printf("%lld\n",ans);
}

猜你喜欢

转载自blog.csdn.net/m0_53688600/article/details/114960273