题解 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;
}
posted @ 2022-04-03 19:49  Little09  阅读(46)  评论(0)    收藏  举报