【UER #7】套路

根号分治好题。

考虑按长度根号分治:

\(len < M\),直接暴力操作:\(O(nM)\)

\(len > M\),则相邻差小于 \(\frac{S}{M - 1}\),枚举相邻差记录前缀值域位置即可。\(O(n\frac{S}{M - 1})\)

\(M = \sqrt S\) 即可。

点击查看代码
//晦暗的宇宙,我们找不到光,看不见尽头,但我们永远都不会被黑色打倒。——Quinn葵因
#include<bits/stdc++.h>
#define ll long long
#define N 200010

int n,m,k,a[N],pr[N],f[N],r,p[N];

int main(){
	scanf("%d%d%d",&n,&m,&k);
	for(int i = 1;i <= n;++i)scanf("%d",&a[i]);
	std::memset(f,63,sizeof(f));
	for(int i = 2;i <= 500;++i)
	for(int j = 1;j + i - 1 <= n;++j){
		f[j] = std::min(std::min(f[j],f[j + 1]),abs(a[i + j - 1] - a[j]));
		if(i >= k)r = std::max(r,f[j] * (i - 1));
	}
	for(int i = 1;i <= n;++i){
		for(int j = 0;j <= 500;++j){
			if(!j)p[j] = std::max(p[j],0);
			else p[j] = std::max(p[j],p[j - 1]);
			if(a[i] - j > 0)p[j] = std::max(p[j],pr[a[i] - j]);
			if(a[i] + j <= m)p[j] = std::max(p[j],pr[a[i] + j]);
			if(i - p[j] >= std::max(k,500))r = std::max(r,(j + 1) * (i - p[j] - 1));
		}
		pr[a[i]] = i;
	}
	std::cout<<r<<"\n";	
}
posted @ 2022-04-25 08:29  fhq_treap  阅读(76)  评论(0编辑  收藏  举报