这个东西他一开始也是草稿
题解
我们考虑在值域上做,设值域为 (m) 。
我们可以考虑数论分块,对于一对 (a_i) 和 (a_j) ,$left lfloor frac{a_i}{a_j} ight floor $ 的取值只有 (sqrt{a_i}) 个,所以我们考虑在相同的取值中取最小的 (a_j) 进行更新答案,就可以得到 (a_i mod a_j) 的最大值。
由于是在值域上做数论分块同时还要维护区间最值,复杂度为 (O(nsqrt m~log~m )) 过不了……
考虑进行优化,我们可以发现这个区间最值是在值域上搞的,可 (O(m)) 预处理,然后复杂度降为 (O(nsqrt m)) 。
然后你再最优化剪枝就过了……
以上。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5,M=1e6+5;
int n,a[N];
int minn[M];
int ans=0;
bool cmp(int a,int b){return a>b;}
int main()
{
cin>>n,memset(minn,63,sizeof(minn));
for(int i=1;i<=n;++i) scanf("%d",&a[i]),minn[a[i]]=a[i];
for(int i=1e6;i>=1;--i) minn[i]=min(minn[i],minn[i+1]);
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;++i)
{
for(int j=ans+1;j<=a[i];j=a[i]/(a[i]/j)+1)
ans=max(ans,a[i]%minn[j]);
}
printf("%d
",ans);
return 0;
}