其他分享
首页 > 其他分享> > 口胡(然而有代码)<第三章>

口胡(然而有代码)<第三章>

作者:互联网

他来了!

估计是最后一章了/kk。

上期精彩:口胡(然而有代码)<第二章>

题目计数:\(101\)

\(101.\) P2659 美丽的序列

提供一种比较屑的 \(\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