#P3720. 第1题-K-统治对的计数
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 460
            Accepted: 93
            Difficulty: 5
            
          
          
          
                       所属公司 : 
                              华为
                                
            
                        
              时间 :2025年9月18日(留学生)-非AI方向(通软&嵌软&测试&算法&数据科学)
                              
                      
          
 
- 
                        算法标签>排序算法          
 
第1题-K-统治对的计数
解题思路
为了正确统计满足条件的下标对 (i,j) 且 i < j,我们需要:
- 保持原始数组的下标关系
 - 对于每个元素 A[j],统计前面有多少个元素 A[i] (i < j) 满足 A[i] - A[j] ≥ K
 
可以采用以下方法:
- 使用归并排序的思想,在排序过程中统计满足条件的对数
 - 或者使用树状数组/线段树来维护元素信息
 
这里我们采用归并排序的变种,在排序过程中统计满足条件的对数:
- 对数组进行归并排序
 - 在合并两个有序子数组时,统计满足 A[i] - A[j] ≥ K 的对数
 - 由于子数组是有序的,可以利用双指针高效统计
 
修正后的复杂度分析
- 
时间复杂度:O(n log n)
- 归并排序的时间复杂度为 O(n log n)
 - 在合并过程中统计满足条件的对数为 O(n)
 
 - 
空间复杂度:O(n)
- 归并排序需要额外的 O(n) 空间
 
 
代码实现
Python
def count_k_dominant_pairs(arr, k):
    # 使用归并排序的思想统计满足条件的对数
    def merge_sort_count(l, r):
        if l >= r:
            return 0
        mid = (l + r) // 2
        count = merge_sort_count(l, mid) + merge_sort_count(mid + 1, r)
        
        # 统计满足条件的对数
        i, j = l, mid + 1
        while i <= mid and j <= r:
            if arr[i] - arr[j] >= k:
                count += mid - i + 1
                j += 1
            else:
                i += 1
        
        # 合并两个有序数组
        temp = []
        i, j = l, mid + 1
        while i <= mid and j <= r:
            if arr[i] <= arr[j]:
                temp.append(arr[i])
                i += 1
            else:
                temp.append(arr[j])
                j += 1
        temp.extend(arr[i:mid + 1])
        temp.extend(arr[j:r + 1])
        arr[l:r + 1] = temp
        
        return count
    
    return merge_sort_count(0, len(arr) - 1)
if __name__ == "__main__":
    import sys
    n = int(sys.stdin.readline())
    arr = list(map(int, sys.stdin.readline().split()))
    k = int(sys.stdin.readline())
    print(count_k_dominant_pairs(arr, k))
Java
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = sc.nextInt();
        }
        int k = sc.nextInt();
        System.out.println(countKDominantPairs(arr, k));
        sc.close();
    }
    private static int countKDominantPairs(int[] arr, int k) {
        return mergeSortCount(arr, 0, arr.length - 1, k);
    }
    private static int mergeSortCount(int[] arr, int left, int right, int k) {
        if (left >= right) {
            return 0;
        }
        int mid = left + (right - left) / 2;
        int count = mergeSortCount(arr, left, mid, k) + mergeSortCount(arr, mid + 1, right, k);
        
        // 统计满足条件的对数
        int i = left, j = mid + 1;
        while (i <= mid && j <= right) {
            if (arr[i] - arr[j] >= k) {
                count += mid - i + 1;
                j++;
            } else {
                i++;
            }
        }
        
        // 合并两个有序数组
        int[] temp = new int[right - left + 1];
        i = left;
        j = mid + 1;
        int t = 0;
        while (i <= mid && j <= right) {
            if (arr[i] <= arr[j]) {
                temp[t++] = arr[i++];
            } else {
                temp[t++] = arr[j++];
            }
        }
        while (i <= mid) {
            temp[t++] = arr[i++];
        }
        while (j <= right) {
            temp[t++] = arr[j++];
        }
        System.arraycopy(temp, 0, arr, left, temp.length);
        
        return count;
    }
}
C++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int mergeSortCount(vector<int>& arr, int left, int right, int k) {
    if (left >= right) {
        return 0;
    }
    int mid = left + (right - left) / 2;
    int count = mergeSortCount(arr, left, mid, k) + mergeSortCount(arr, mid + 1, right, k);
    
    // 统计满足条件的对数
    int i = left, j = mid + 1;
    while (i <= mid && j <= right) {
        if (arr[i] - arr[j] >= k) {
            count += mid - i + 1;
            j++;
        } else {
            i++;
        }
    }
    
    // 合并两个有序数组
    vector<int> temp;
    i = left;
    j = mid + 1;
    while (i <= mid && j <= right) {
        if (arr[i] <= arr[j]) {
            temp.push_back(arr[i++]);
        } else {
            temp.push_back(arr[j++]);
        }
    }
    while (i <= mid) {
        temp.push_back(arr[i++]);
    }
    while (j <= right) {
        temp.push_back(arr[j++]);
    }
    copy(temp.begin(), temp.end(), arr.begin() + left);
    
    return count;
}
int countKDominantPairs(vector<int>& arr, int k) {
    return mergeSortCount(arr, 0, arr.size() - 1, k);
}
int main() {
    int n;
    cin >> n;
    vector<int> arr(n);
    for (int i = 0; i < n; ++i) {
        cin >> arr[i];
    }
    int k;
    cin >> k;
    cout << countKDominantPairs(arr, k) << endl;
    return 0;
}
        题目内容
给定一个整数数组 A,长度为 n 。在给定一个整数 K ,定义下标对 (i,j)(满足i<j),如果 A[i]−A[j]≥K,为「K-统治对」。
统计并返回数组中所有「K-统治对」的数量。
输入描述
数组长度 n ;范围 [1,100000]
数组各元素,用空格分隔,元素取值范围 [−100000,100000]
整数 K
输出描述
输出一个整数,表示数组中所有「K-统治对」的数量。
样例1
输入
5
-3 -1 -6 2 0
2
输出
3
说明
满足 A[i]−A[j]>=2 且 i<j 的下标对如下:
(0,2):−3−(−6)=3>=2
(1,2):−1−(−6)=5>=2
(3,4):2−0=2>=2
故最终计数为 3 。
样例2
输入
5
2 9 4 7 1
2
输出
5
说明
满足 A[i]−A[j]>=2 且 i<j 的下标对如下:
(1,2):9−4=5>=2
(1,3):9−7=2>=2
(1,4):9−1=8>=2
(2,4):4−1=3>=2
(3,4):7−1=6>=2
共计 5 个。