Problem Author: | Khoi Le |
Prepared by: | Khoi Le |
Edited by: | Hasan Saleh (MathModel) |
Observation : The minimum value is always achieved when either the index distance or the value difference is small.
We want to minimize V = |p_i - p_j| \cdot |i - j|. We shall prove that we only need to check such that |i - j| \le \sqrt{n} or |p_i - p_j| \le \sqrt{n}.
Proof:
Let the minimum product for index be \text{ans}_i. We can always pick a such that |p_i - p_j| = 1 (by choosing the value p_i+1 or p_i-1). Since |i - j| < n, it follows that \text{ans}_i < 1 \cdot n = n.
Now, suppose there exists an optimal such that both |i - j| > \sqrt{n} and |p_i - p_j| > \sqrt{n}. Then:
This contradicts our finding that \text{ans}_i < n. Therefore, at least one of the factors must be \le \sqrt{n}. In the implementation, we use C = 2\sqrt{n} to provide a safe constant margin.
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
int n;cin>>n;
vector<int>p(n);
for(auto &i:p)cin>>i;
vector<int>mp(n+1);
for(int i=0;i<n;i++){
mp[p[i]]=i;
}
for(int i=0;i<n;i++){
//we first look by index
int c=sqrtl(n)*2;
int ans=1000'000'000'000LL;
for(int j=max(0LL,i-c);j<=min(n-1,i+c);j++){
if(j!=i)ans=min(ans,abs(p[i]-p[j])*abs(i-j));
}
//second we look by value of p[i]
int cur=p[i];
for(int j=max(1LL,p[i]-c);j<=min(n,p[i]+c);j++){
if(j!=cur){
ans=min(ans,abs(j-cur)*abs(mp[j]-mp[cur]));
}
}
cout<<ans<<" ";
}
cout<<"\n";
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t=1;cin>>t;
while(t--) solve();
}