Thống kê bộ ba tăng dần

Nguồn: Đề thi Blue Bridge Cup tỉnh

Mô tả bài toán

Cho ba mảng số nguyên:

A = [A₁, A₂, ..., Aₙ]
B = [B₁, B₂, ..., Bₙ]
C = [C₁, C₂, ..., Cₙ]

Đếm số bộ ba (i, j, k) thỏa mãn:

1 ≤ i, j, k ≤ N
Aᵢ < Bⱼ < Cₖ

Định dạng nhập

  • Dòng 1: Số nguyên N
  • Dòng 2: N số nguyên A₁...Aₙ
  • Dòng 3: N số nguyên B₁...Bₙ
  • Dòng 4: N số nguyên C₁...Cₙ

Định dạng xuất

Một số nguyên duy nhất là kết quả.

Giới hạn dữ liệu

1 ≤ N ≤ 10⁵
0 ≤ Aᵢ, Bᵢ, Cᵢ ≤ 10⁵

Ví dụ

Nhập:
3
1 1 1
2 2 2
3 3 3

Xuất:
27

Phương pháp: Với mỗi phần tử Bⱼ, đếm số phần tử trong A nhỏ hơn Bⱼ và số phần tử trong C lớn hơn Bⱼ. Tổng số bộ ba hợp lệ là tích hai giá trị này.

Giải pháp 1: Tổng tiền tố

#include<iostream>
#include<cstring>
using namespace std;

typedef long long LL;
const int MAX = 100010;
int arrA[MAX], arrB[MAX], arrC[MAX];
int cntA[MAX], cntC[MAX], temp[MAX];

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) cin >> arrA[i], arrA[i]++;
    for (int i = 0; i < n; i++) cin >> arrB[i], arrB[i]++;
    for (int i = 0; i < n; i++) cin >> arrC[i], arrC[i]++;

    // Đếm phần tử trong A
    for (int i = 0; i < n; i++) temp[arrA[i]]++;
    for (int i = 1; i < MAX; i++) temp[i] += temp[i - 1];
    for (int i = 0; i < n; i++) cntA[i] = temp[arrB[i] - 1];

    memset(temp, 0, sizeof temp);

    // Đếm phần tử trong C
    for (int i = 0; i < n; i++) temp[arrC[i]]++;
    for (int i = 1; i < MAX; i++) temp[i] += temp[i - 1];
    for (int i = 0; i < n; i++) cntC[i] = temp[MAX - 1] - temp[arrB[i]];

    LL result = 0;
    for (int i = 0; i < n; i++) result += (LL)cntA[i] * cntC[i];
    cout << result;
}

Giải pháp 2: Tìm kiếm nhị phân

#include<iostream>
#include<algorithm>
using namespace std;

typedef long long LL;
const int MAX = 100010;
int arrA[MAX], arrB[MAX], arrC[MAX];

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) cin >> arrA[i];
    for (int i = 0; i < n; i++) cin >> arrB[i];
    for (int i = 0; i < n; i++) cin >> arrC[i];

    sort(arrA, arrA + n);
    sort(arrB, arrB + n);
    sort(arrC, arrC + n);

    LL total = 0;
    for (int i = 0; i < n; i++) {
        // Đếm phần tử trong A nhỏ hơn arrB[i]
        LL countA = lower_bound(arrA, arrA + n, arrB[i]) - arrA;
        // Đếm phần tử trong C lớn hơn arrB[i]
        LL countC = n - (upper_bound(arrC, arrC + n, arrB[i]) - arrC);
        total += countA * countC;
    }
    cout << total;
}

Thẻ: thuật toán tổng tiền tố tìm kiếm nhị phân Blue Bridge Bộ ba

Đăng vào ngày 12 tháng 7 lúc 11:53