題解 CF1654E Arithmetic Operations
阿新 • • 發佈:2022-04-03
容易發現,題意可以轉化為:對於所有公差 \(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\)
#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; }