题解 CF1654E Arithmetic Operations
容易发现,题意可以转化为:对于所有公差 \(k\),把序列第 \(i\) 个数修改为 \(a_i-i\times k\),最多有多少个相等的数。
当 \(|k|\ge 10^5\) 时,必然不可能相等。因此只要考虑 \(-10^5<k<10^5\) 的情况。
考虑两个数距离为 \(dis\) 时,只有 \(dis\times |k|\le 10^5\) 才可能相等。因此,当 \(k\) 比较大的时候,每个数只可能和它后(前)面的 \(\lfloor \dfrac{n}{k}\rfloor\) 个数相等。且如果 \(i\) 位置与 \(j\) 位置相等,\(k\) 是可以唯一确定的。
根号分治即可。取阈值为 \(lim\),第一部分暴力枚举公差 \(O(lim\times n)\),第二部分枚举第一个相等的数以及它后面 \(\lfloor \dfrac{n}{k}\rfloor\) 个数,复杂度 \(O(\dfrac{n^2}{lim}\))。所以当 \(lim=\sqrt{n}\),复杂度是 \(O(n\sqrt{n})\)。需要开 \(O(n\sqrt{n})\) 大小的桶记录。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(x) memset(x,0,sizeof(x))
#define printYes puts("Yes")
#define printYES puts("YES")
#define printNo puts("No")
#define printNO puts("NO")
#define lowbit(x) (x&(-x))
const ll inf=1000000000000000000;
//const ll mod=998244353;
//const ll mod=1000000007;
const int N=100005,B=321,K=N*B+2*N;
int n,m,ans;
int a[N];
int b[N*B*2+4*N],c[N];
inline int read()
{
int F=1,ANS=0;
char C=getchar();
while (C<'0'||C>'9')
{
if (C=='-') F=-1;
C=getchar();
}
while (C>='0'&&C<='9')
{
ANS=ANS*10+C-'0';
C=getchar();
}
return F*ANS;
}
int main()
{
n=read();
for (int i=1;i<=n;i++) a[i]=read();
for (int i=-B;i<=B;i++)
{
for (int j=1;j<=n;j++)
{
b[a[j]-i*j+K]++;
ans=max(ans,b[a[j]-i*j+K]);
}
for (int j=1;j<=n;j++)
{
b[a[j]-i*j+K]--;
}
}
for (int i=1;i<=n;i++)
{
int r=min(n,i+B);
for (int j=i+1;j<=r;j++)
{
int det=a[j]-a[i],len=j-i;
if (det%len!=0) continue;
int k=det/len;
b[k+K]++;
ans=max(ans,b[k+K]+1);
}
for (int j=i+1;j<=r;j++)
{
int det=a[j]-a[i],len=j-i;
if (det%len!=0) continue;
int k=det/len;
b[k+K]--;
}
}
cout << n-ans;
return 0;
}