题意:一个数列,找出两个数a[i], a[j],使得s = max(|j - i| * min(a[i], a[j]))最大,求最大值。
要求:n<=1e6,使用O(nlogn)算法会超时。
解法:f(le,ri):
对于一个区间[le,ri],先用le和ri更新答案
维护两个指针一个指向le,一个指向ri,现在将指向小元素的指针向另一边移动,
中间遇见元素a[p],
如果a[p]<min(a[le],a[ri]),忽略。
否则答案=f(p,ri)(如果a[le]<a[ri]) || f(le,p) (如果a[le]>=a[ri])
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
typedef long long ll;
typedef pair<int, int> pii;
const int INF =0x3f3f3f3f;
const int maxn=1000000 ;
ll ans;int n,a[maxn+10];
void cope(int le,int ri)
{
ans=max(ans,(ll)(ri-le)*min(a[ri],a[le]) );
switch(a[le]>a[ri])
{
case true:
for(int p=ri-1;p>le;p--)
{
if(a[p]<=a[ri]) continue;
else
{
cope(le,p);
return;
}
}
case false:
for(int p=le+1;p<ri;p++)
{
if(a[p]<=a[le]) continue;
else
{
cope(p,ri);
return;
}
}
}
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for1(i,n)
{
scanf("%d",&a[i]);
}
ans=0;
cope(1,n);
printf("%lld\n",ans);
}
return 0;
}