题解 [CF1654E] Arithmetic Operations
看完题解十分想锤墙
考虑对公差根号分治
当公差 \(d\leqslant \sqrt m\) 时,可以枚举公差
那么对每个数考虑若这个数在等差数列中的话那么这个等差数列的第 1 项是多少
对这个东西开桶求众数即可
当 \(d>\sqrt m\) 时,可以枚举首项
那么向后扫 \(\sqrt m\) 项,对 \(\frac{a_j-a_i}{j-i}\) 开桶即可
注意是 \(\sqrt m\) 不是 \(\sqrt n\)!
复杂度 \(O(n\sqrt m)\)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define fir first
#define sec second
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n;
int a[N], sqr, ans;
struct hash_map{
static const int SIZE=5000010;
int head[SIZE], sta[SIZE], size, top;
struct node{int val, next, dat;}e[SIZE<<1];
hash_map(){memset(head, -1, sizeof(head));}
inline int end() {return -1;}
inline int& operator [] (int t) {
int t2=1ll*abs(t)*98244353%SIZE;
if (head[t2]==-1) sta[++top]=t2;
for (int i=head[t2]; ~i; i=e[i].next)
if (e[i].dat==t) return e[i].val;
e[++size]={0, head[t2], t}; head[t2]=size;
return e[size].val;
}
inline int find(int t) {
int t2=1ll*abs(t)*98244353%SIZE;
for (int i=head[t2]; ~i; i=e[i].next)
if (e[i].dat==t) return 1;
return -1;
}
inline int qmax() {
int ans=0;
for (int i=1; i<=top; ++i)
for (int j=head[sta[i]]; ~j; j=e[j].next)
ans=max(ans, e[j].val);
return ans;
}
void clear() {
while (top) head[sta[top--]]=-1;
size=0;
}
}mp;
void solve() {
sqr=ceil(sqrt(100000));
for (int d=0; d<=sqr; ++d) {
mp.clear();
for (int i=1; i<=n; ++i) ++mp[a[i]-i*d];
ans=max(ans, mp.qmax());
}
for (int i=1; i<=n; ++i) {
mp.clear();
for (int j=i+1; j<=min(i+sqr,n); ++j)
if ((a[j]-a[i])%(j-i)==0)
++mp[(a[j]-a[i])/(j-i)];
ans=max(ans, mp.qmax()+1);
}
}
signed main()
{
n=read();
for (int i=1; i<=n; ++i) a[i]=read();
solve();
reverse(a+1, a+n+1);
solve();
cout<<n-ans<<endl;
return 0;
}