题目链接

最大 FST 距离

题目描述

给定 个元素,第 个元素具有特征值 。定义两个元素 之间的 FST 距离为:

请计算所有元素对中的最大 FST 距离。

解题思路

这是一个求解最大距离的问题。如果采用暴力法,遍历所有可能的元素对 来计算距离,时间复杂度将是 ,对于 较大的情况会超时。因此,我们需要对公式进行分析和优化。

1. 公式分析与几何解释 FST 距离的公式 实际上是二维平面上两点之间的曼哈顿距离。 我们可以将每个元素 看作是平面上的一个点 ,其坐标为 。这样,FST 距离 就是点 之间的曼哈顿距离。问题就转化为了:在由 个点组成的点集中,找出曼哈顿距离最远的一对点。

2. 曼哈顿距离与切比雪夫距离的转换 直接在点集中寻找最远曼哈顿距离仍然不容易。这里有一个重要的几何变换技巧:将坐标系旋转45度,可以实现曼哈顿距离和切比雪夫距离的相互转换。

对于任意两点 ,它们的曼哈顿距离为 。 我们进行坐标变换,令 。那么在新坐标系中,点 变为 。 可以证明,原坐标系中的曼哈顿距离等于新坐标系中的切比雪夫距离,即:

3. 问题简化 现在,问题变成了在新坐标系中寻找最远的切比雪夫距离。一个点集中最远的切比雪夫距离为: 就是所有 值中的最大值与最小值的差,即 max(u) - min(u)。同理,

所以,最终的最大 FST 距离就是 max(max(u) - min(u), max(v) - min(v))

4. 算法步骤

  1. 根据原问题,我们定义的点的坐标是
  2. 进行坐标变换,计算每个元素 对应的新坐标分量
  3. 我们只需要遍历一次所有元素,在遍历过程中同时找出 的最大值、最小值和 的最大值、最小值。
  4. 计算出 max_u - min_umax_v - min_v
  5. 这两者中的较大值就是我们要求的最大 FST 距离。

这个算法只需要一次遍历,时间复杂度为 。由于 的值可能很大,需要使用长整型(long long)来存储。

代码

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    
    int n;
    cin >> n;
    
    long long max_u = -2e18, min_u = 2e18;
    long long max_v = -2e18, min_v = 2e18;
    
    for (long long i = 1; i <= n; ++i) {
        long long a;
        cin >> a;
        
        long long u = i * i + a * a;
        long long v = i * i - a * a;
        
        max_u = max(max_u, u);
        min_u = min(min_u, u);
        max_v = max(max_v, v);
        min_v = min(min_v, v);
    }
    
    cout << max(max_u - min_u, max_v - min_v) << endl;
    
    return 0;
}
import java.util.Scanner;
import java.lang.Math;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        long[] a = new long[n];
        for (int i = 0; i < n; i++) {
            a[i] = sc.nextLong();
        }
        
        long maxU = Long.MIN_VALUE;
        long minU = Long.MAX_VALUE;
        long maxV = Long.MIN_VALUE;
        long minV = Long.MAX_VALUE;
        
        for (long i = 0; i < n; i++) {
            long idx = i + 1;
            long val = a[(int)i];
            
            long u = idx * idx + val * val;
            long v = idx * idx - val * val;
            
            maxU = Math.max(maxU, u);
            minU = Math.min(minU, u);
            maxV = Math.max(maxV, v);
            minV = Math.min(minV, v);
        }
        
        long dist = Math.max(maxU - minU, maxV - minV);
        System.out.println(dist);
    }
}
import sys

def solve():
    n = int(sys.stdin.readline())
    a = list(map(int, sys.stdin.readline().split()))
    
    max_u = -float('inf')
    min_u = float('inf')
    max_v = -float('inf')
    min_v = float('inf')
    
    for i in range(n):
        idx = i + 1
        val = a[i]
        
        u = idx*idx + val*val
        v = idx*idx - val*val
        
        max_u = max(max_u, u)
        min_u = min(min_u, u)
        max_v = max(max_v, v)
        min_v = min(min_v, v)
        
    result = max(max_u - min_u, max_v - min_v)
    print(result)

solve()

算法及复杂度

  • 算法:坐标变换 + 单次遍历
  • 时间复杂度:我们只需要对输入数组进行一次遍历,以找到变换后坐标分量的最大值和最小值。因此,总时间复杂度为
  • 空间复杂度:我们只需要常数个变量来存储最大值和最小值,因此空间复杂度为 (不考虑输入数组的存储)。