大佬能不能康康这个做法在随机数据下的复杂度
查看原帖
大佬能不能康康这个做法在随机数据下的复杂度
224358
清平乐楼主2020/8/24 16:34

rt

自己脑补了一个做法,但是 T 了

ii 枚举峰顶

find 函数:如果 k=0k=0,处理峰顶左边的区间;否则处理右边

以处理左边为例:找到 [l,r][l,r] 中最小的数 xx,其下标为 yy,那么 [l,y][l,y] 的贡献可以直接算,然后递归处理 [y+1,r][y+1,r]

显然能被卡成 O(n2)O(n^2)

但如果在随机数据下的复杂度大概是多少呢? ( swap 在 c++11 下交换 vector 大概是 O(1)O(1) 的)

#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;

const int N=5e5+5;
int n,id;
long long ans;
int m[N];
pair<int,int> st[N][25];
vector<pair<int,int> > color(N),a(N);

inline void RMQ(void)
{
	for(register int i=1;i<=n;++i)
		st[i][0]=make_pair(m[i],i);
	register int t=log2(n);
	for(register int j=1;j<=t;++j)
		for(register int i=1;i+(1<<j)-1<=n;++i)
			st[i][j]=min(st[i][j-1],st[i+(1<<j-1)][j-1]);
}

inline pair<int,int> query(int l,int r)
{
	register int t=log2(r-l+1);
	return min(st[l][t],st[r-(1<<t)+1][t]);
}

long long find(int id,int l,int r,bool k)
{
	if(l>r) return 0;
	pair<int,int> t=query(l,r);
	color[t.second]=make_pair(t.first,id);
	if(k) return 1ll*t.first*(r-t.second+1)+find(id,l,t.second-1,k);
	else return 1ll*t.first*(t.second-l+1)+find(id,t.second+1,r,k);
}

int main(void)
{
	scanf("%d",&n);
	for(register int i=1;i<=n;++i)
		scanf("%d",m+i);
	RMQ();
	for(register int i=1;i<=n;++i)
	{
		register long long res=find(i,1,i,0)+find(i,i,n,1)-m[i];
		if(res>ans)
		{
			ans=res,id=i;
			swap(a,color);
		}
	}
	for(register int i=id-1;i>=1;--i)
		if(a[i].second!=id||!a[i].first) a[i].first=a[i+1].first;
	for(register int i=id+1;i<=n;++i)
		if(a[i].second!=id||!a[i].first) a[i].first=a[i-1].first;
	for(register int i=1;i<=n;++i)
		printf("%d ",a[i].first);
	return 0;
}
2020/8/24 16:34
加载中...