口胡(然而有代码)<第三章>
作者:互联网
他来了!
估计是最后一章了/kk。
上期精彩:口胡(然而有代码)<第二章>
题目计数:\(101\)
提供一种比较屑的 \(\mathcal O(n\log n)\) 解法。
当然常数很小。。。。
首先考虑到将这些数钦定为最小值,然后去找区间,易证答案一定来自于满足此值最小的最长区间。
我们于是可以从最大值开始枚举,判断他的两侧已经有多少被枚举过了(这些数一定比他大),然后算就完了。
可是如何判断已经被枚举的最左,最右在哪里呢。
我们把已被用的搞成区间,记录一下左右端点,然后不断计算,扩展即可得到答案。
具体见代码:
#include"algorithm"
#include"iostream"
#include"cstdio"
#include"cmath"
using namespace std;
#define read(x) scanf("%d",&x)
#define ll long long
#define MAXN 2000005
int n;
int num[MAXN];
int t[MAXN],l[MAXN],r[MAXN];
struct node
{
int val,id;
}a[MAXN];
int cnt=0;
ll ans=0;
bool cmp(node n,node m){return n.val>m.val;}
void hsh()
{
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++) num[++cnt]=a[i].id;
return;
}
int main()
{
read(n);
for(int i=1;i<=n;i++) read(a[i].val),t[i]=a[i].val,a[i].id=i;
hsh();
for(int i=1;i<=n;i++)
{
int j=num[i],len=1;
if(l[j-1]) len=len+(j-l[j-1]);
if(r[j+1]) len=len+(r[j+1]-j);
ans=max(ans,(ll)len*(ll)t[j]);
if(l[j-1]&&r[j+1])
{
int op=l[j-1],rt=r[j+1];
l[j-1]=0,r[j+1]=0;
r[op]=rt,l[rt]=op;
}
else if(l[j-1])
{
int t=l[j-1];
l[j-1]=0,l[j]=t,r[t]=j;
}
else if(r[j+1])
{
int t=r[j+1];
r[j+1]=0,r[j]=t,l[t]=j;
}
else l[j]=r[j]=j;
}
printf("%lld\n",ans);
return 0;
}
标签:node,val,int,代码,然而,MAXN,include,define 来源: https://www.cnblogs.com/tlx-blog/p/13900267.html