1. 程式人生 > 實用技巧 >題解 CF484B 【Maximum Value】

題解 CF484B 【Maximum Value】

題解

我們考慮在值域上做,設值域為 \(m\)

我們可以考慮數論分塊,對於一對 \(a_i\)\(a_j\) ,$\left \lfloor \frac{a_i}{a_j} \right \rfloor $ 的取值只有 \(\sqrt{a_i}\) 個,所以我們考慮在相同的取值中取最小的 \(a_j\) 進行更新答案,就可以得到 \(a_i \bmod a_j\) 的最大值。

由於是在值域上做數論分塊同時還要維護區間最值,複雜度為 \(O(n\sqrt m~log~m )\) 過不了……

考慮進行優化,我們可以發現這個區間最值是在值域上搞的,可 \(O(m)\) 預處理,然後複雜度降為 \(O(n\sqrt 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\n",ans);
	return 0;
}