Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

Reverse Pairs: นับคู่ย้อนกลับสำคัญใน C++

ปัญหา

กำหนดอาร์เรย์ หาจำนวน Important Reverse Pairs คือคู่ (i, j) ที่ i < j และ nums[i] > 2 × nums[j]

ตัวอย่าง: [2,8,7,7,2] → 3 คู่: (8,2), (7,2), (7,2) (indices: (1,4), (2,4), (3,4))

แนวคิด: Modified Merge Sort (Divide & Conquer)

นับคู่ข้ามกลาง (Cross Pairs) ระหว่าง Merge Step

Merge Step Modification

ปกติ Merge: รวม 2 sorted halves

นับ Reverse Pairs: สำหรับแต่ละ i ใน Left Half หา first ใน Right Half แรกที่ 2*right[first] < left[i]


while (i <= mid) {
    while (first <= high && 2LL * a[first] < a[i]) first++;
    ans += first - (mid + 1);
    // ... merge logic
}

โค้ด C++

#include <bits/stdc++.h>
using namespace std;
typedef long long int lli;

class Solution {
    int ans = 0;
    
    void merge(vector<int>& a, lli low, lli mid, lli high) {
        lli k = high - low + 1;
        vector<lli> temp(k);
        lli i = low, j = mid + 1;
        k = 0;
        lli first = mid + 1;
        
        while (i <= mid) {
            // นับ reverse pairs: หา first ใน right half ที่ 2*a[first] < a[i]
            while (first <= high && (lli)a[first] * 2 < (lli)a[i]) {
                first++;
            }
            
            // Merge: copy smaller elements from right
            while (j <= high && a[j] <= a[i]) {
                temp[k++] = a[j++];
            }
            
            ans += first - (mid + 1);  // จำนวน valid pairs สำหรับ a[i]
            temp[k++] = a[i++];
        }
        
        while (j <= high) temp[k++] = a[j++];
        
        // Copy back
        k = 0;
        for (lli idx = low; idx <= high; idx++) {
            a[idx] = temp[k++];
        }
    }
    
    void mergeSort(vector<int>& a, lli low, lli high) {
        if (low >= high) return;
        lli mid = low + (high - low) / 2;
        mergeSort(a, low, mid);
        mergeSort(a, mid + 1, high);
        merge(a, low, mid, high);
    }
    
public:
    int reversePairs(vector<int>& nums) {
        ans = 0;
        mergeSort(nums, 0, nums.size() - 1);
        return ans;
    }
};

int main() {
    Solution ob;
    vector<int> v = {2, 8, 7, 7, 2};
    cout << ob.reversePairs(v);  // 3
    return 0;
}

ความซับซ้อน

  • Time: O(n log n) - เหมือน Merge Sort
  • Space: O(n) - Temporary array

Input / Output

Input:  {2,8,7,7,2}
Output: 3

หมายเหตุ

ใช้ long long สำหรับการคูณ 2 เพื่อป้องกัน Overflow