Editorial for Đếm cặp đôi (HSG'20)
Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.
Submitting an official solution before solving the problem yourself is a bannable offence.
Spoiler Alert
Hint 1
Đề yêu cầu \((A_i, A_j)\) thỏa \(A_i + A_j = x\)
<=> Với mỗi \(Ai\) tìm số lượng số \(A_j\) thỏa \(x - A_i == A_j\) và loại ra khỏi mảng
Hint 2
Lưu các số và tần số của nó vào một mảng, có thể sử dụng CTDL
std::map
cho đơn giảnĐể loại khỏi mảng, ta có thể thực hiện gán tần_số\((A_j)\) = 0 thay vì duyệt qua và xóa
Hint 3
Công thức tính
- Gọi (nx, fx) là số Ai bất kì và tấn số của nó trong mảng
- Số còn lại là (ny, fy) là số Aj = x - Ai và tần số của nó trong mảng
- Khi nx # ny thì res += fx * fy (có fx cách chọn Ai và fy cách chọn Aj)
- Khi nx = ny thì res += fx * (fx - 1) / 2 (có fx cách chọn Ai và (fx - 1) cách chọn Aj khác Ai)
Reference AC code | O(n log n) time | O(n) auxiliary space | STL, Combinatorics
C++
int main()
{
/// Input
int n = readInt();
int k = readInt();
/// Nhan vao mang bieu dien duoi dang <gia tri, tan so>
map<int, int> M;
while (n--) M[readInt()]++;
ll res = 0;
for (pair<int, int> e : M)
{
/// Tim cap (nx, ny) = (Ai, Aj) thoa (nx + ny = k) va tan so cua no (fx, fy)
int nx = e.first; int fx = e.second;
int ny = k - e.first; int fy = M[ny];
M.erase(ny); /// xoa phan tu khoi mang
if (nx == ny) res += 1LL * fx * (fx - 1) / 2; /// Co (fx cach chon nx va fx - 1 cach chon ny khac nx)
else res += 1LL * fx * fy; /// Co (fx cach chon nx va fy cach chon ny)
}
/// Xuat ket qua
cout << res;
return 0;
}
Comments