【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";
}