trang chủ / bài tập / friendcross / lời giải

Giao Nhau Của Những Người Bạn

Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Tác giả: huunguyenhuunguyen

Lời giải: Giao Nhau Của Những Người Bạn

Hướng tiếp cận

Đây là bài toán đếm nghịch thế (inversion counting) với điều kiện lọc. Thay vì đếm trực tiếp các cặp không thân thiện mà giao nhau, ta dùng:

Kết quả=Tổng giao nhauGiao nhau thân thiện

trong đó:

  • Tổng giao nhau: tổng số cặp bò giao nhau (không kể điều kiện thân thiện).
  • Giao nhau thân thiện: số cặp thân thiện (|ab|K) mà giao nhau.

Nhận xét quan trọng

  1. Gọi ra[x] là vị trí của giống bò x ở bên trái, rb[x] là vị trí ở bên phải. Hai giống xy giao nhau khi và chỉ khi (ra[x]ra[y])(rb[x]rb[y]) trái dấu.

  2. Tổng giao nhau bằng số nghịch thế trong dãy rb[a[1]],rb[a[2]],,rb[a[N]] (trong đó a[i] là giống bò ở vị trí i bên trái). Đây là bài toán đếm nghịch thế cổ điển, giải bằng BIT (Binary Indexed Tree) trong O(NlogN).

  3. Để đếm giao nhau thân thiện, xét các cặp (a[i],a[j]) với i<j (tức ra[a[i]]<ra[a[j]]) mà |a[i]a[j]|Krb[a[i]]>rb[a[j]]. Ta cần đếm số nghịch thế trong không gian 2D: với điều kiện về giá trị giống bò VÀ về vị trí bên phải.

Thuật toán

Bước 1: Đếm tổng nghịch thế (O(N log N))

Xây dựng dãy c[i]=rb[a[i]] với i=1N. Đếm số nghịch thế trong c bằng BIT: duyệt từ trái sang phải, với mỗi c[i] đếm số phần tử đã xét lớn hơn c[i].

Bước 2: Đếm nghịch thế thân thiện (O(N log² N))

Duyệt theo thứ tự bên trái (i=1N). Tại bước i, giống bò a[i]ra[a[i]]=i. Ta cần đếm số j<i thỏa:

  • |a[j]a[i]|K (thân thiện theo giống)
  • rb[a[j]]>rb[a[i]] (giao nhau vì ra[a[j]]<ra[a[i]] nhưng rb[a[j]]>rb[a[i]])

Dùng cây phân đoạn merge-sort (merge sort tree) đánh chỉ số theo giá trị giống bò [1N]. Mỗi nút của cây lưu danh sách đã được sắp xếp các giá trị rb của các giống bò đã được chèn vào phạm vi đó.

  • Truy vấn: với giống a[i], đếm các phần tử trong phạm vi giống [max(1,a[i]K),min(N,a[i]+K)]rb>rb[a[i]]. Mỗi truy vấn mất O(log2N) (đi qua O(logN) nút, mỗi nút tìm nhị phân trong danh sách sắp xếp).
  • Chèn: sau khi truy vấn, chèn (a[i],rb[a[i]]) vào cây.

Lưu ý: Ta truy vấn trước khi chèn, đảm bảo chỉ đếm j<i.

Kết quả

Output=Tổng nghịch thếNghịch thế thân thiện

Độ phức tạp

  • Thời gian: O(Nlog2N)
    • Bước 1: O(NlogN)
    • Bước 2: O(Nlog2N) — mỗi trong N bước có O(log2N) cho truy vấn và O(logN) cho chèn
  • Bộ nhớ: O(NlogN) — cây phân đoạn merge-sort lưu tổng O(NlogN) phần tử

Bình luận

Không có bình luận tại thời điểm này.

gnatmake 12.2.0 a68g 3.1.2 nasm 2.16.1 as_x64 2.46 awk 1.3.4 gcc 16.1.0 csc 6.12.0.200 g++ 16.1.0 g++-themis 16.1.0 g++17 16.1.0 g++20 16.1.0 g++23 16.1.0 clang++ 22.1.6 dmd 2.112.0 dart 3.12.1 gforth 0.7.3 gfortran 12.2.0 go 1.26.3 groovyc 5.0.6 javac 25.0.3 node 26.2.0 kotlinc 2.3.21 sbcl 2.2.9 lua 5.4.8 nim 2.2.10 fpc 3.2.2 fpc-themis 3.2.2 perl 5.36.0 php 8.5.6 pike 8.0 pypy3 7.3.23 python3 3.14.5 racket 8.7 ruby 4.0.5 rustc 1.96.0 csc 5.3.0 ctoj-scratch 0.0.1 sed 4.9 tclsh 8.6 bun 1.3.14 deno 2.8.1 v 0.5.1 zig 0.16.0