题意:
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/764ae36f842c49b2bf7255edd442a20f.png)
解法:
题目问的是最少要修改多少个数,
可以将问题转换为最多保留多少个数。
设公差为d, sq=sqrt(1e5)
1. 当d<=sq时:
如果某个a[i]不需要修改,则其对应的a[0]=a[i]-i*d
对于a[0]相同的a[k] (1<=k<=n), 一定能同时保留.
枚举d,用map计算a[0]的众数即可.
复杂度O(n*sq)
2. 当d>sq时:
假设a[i]和a[j]都保留下来了,
由于a[i]=a[0]+i*d, a[j]=a[0]+j*d,
可推出a[j]-a[i]=(i-j)*d,
由于d>sq, 且a[i]<=1e5, 所以有(i-j)<=1e5/d<=1e5/sq,
这意味着保留下来的的a[i]和a[j]之间的最大距离一定不超过1e5/sq,
我们枚举i, 在[i,i+1e5/sq]范围内枚举j,则d=(a[j]-a[i])/(j-i).
用map计算d的众数即可.
复杂度O(1e5/sq*n)=O(sq*n)
总复杂度O(n*sq)
Code:
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define int long long
#define PI pair<int, int>
const int maxm=1e5+5;
const int mod=1e9+7;
int n;
int a[maxm];
const int sq=333;
int cnt[maxm*sq+maxm];
int cal1(){
int ma=0;
for(int d=-sq;d<=sq;d++){
const int base=d>=0?n*sq:0;
for(int i=1;i<=n;i++){
int a0=a[i]-i*d;
cnt[a0+base]++;
assert(a0+base>=0);
assert(a0+base<maxm*sq+maxm);
ma=max(ma,cnt[a0+base]);
}
for(int i=1;i<=n;i++){
int a0=a[i]-i*d;
cnt[a0+base]=0;
}
}
return ma;
}
int cal2(){
int ma=0;
for(int i=1;i<=n;i++){
const int base=1e5;
for(int j=i+1;j<=n&&j-i<=1e5/sq;j++){
int dif=a[j]-a[i];
int len=j-i;
if(dif%len!=0)continue;
int d=dif/len;
cnt[d+base]++;
assert(d+base>=0);
ma=max(ma,cnt[d+base]);
}
for(int j=i+1;j<=n&&j-i<=1e5/sq;j++){
int dif=a[j]-a[i];
int len=j-i;
if(dif%len!=0)continue;
int d=dif/len;
cnt[d+base]=0;
}
}
return ma+1;
}
void solve() {
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int ans=0;
ans=max(ans,cal1());
ans=max(ans,cal2());
cout<<n-ans<<endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
#ifndef ONLINE_JUDGE
freopen("../in.txt", "r", stdin);
freopen("../out.txt", "w", stdout);
#endif
#ifdef MULTI_CASE
int T;
cin >> T;
while (T--)
#endif
solve();
return 0;
}