canuc80k6500·1/50

Đa tập có thứ tự

Nộp bài trên LQDOJ

Bài 65 · Balanced Binary Search Tree

Duy trì một đa tập số nguyên. Có sáu loại thao tác: chèn một giá trị, xóa đúng một bản sao, hỏi hạng của một giá trị, hỏi phần tử nhỏ thứ , hỏi tiền nhiệm nghiêm ngặt và hỏi kế nhiệm nghiêm ngặt. Mọi truy vấn cần được trả lời theo trạng thái hiện tại của đa tập.

Các phần tử bằng nhau được tính thành nhiều bản sao riêng. Hạng của là cộng với số phần tử đang nhỏ hơn ; tiền nhiệm và kế nhiệm đều là nghiêm ngặt.

Mỗi lệnh có một trong sáu ý nghĩa sau:

  • : thêm một bản sao của ;
  • : xóa một bản sao của ;
  • : hỏi hạng của ;
  • : hỏi phần tử nhỏ thứ , đánh số từ và tính cả các bản sao;
  • : hỏi giá trị lớn nhất nhỏ hơn ;
  • : hỏi giá trị nhỏ nhất lớn hơn .

Input

  • Dòng đầu chứa số thao tác .
  • Mỗi dòng trong số dòng tiếp theo chứa hai số nguyên theo một trong sáu dạng đã mô tả.

Output

  • Với mỗi lệnh loại , in đáp án trên một dòng.

Constraints

  • .
  • Dữ liệu bảo đảm mọi truy vấn phần tử thứ , tiền nhiệm và kế nhiệm đều có đáp án hợp lệ.

Scoring

  • Subtask small: điểm, gồm test nhỏ.
  • Subtask full: điểm, gồm test không có giới hạn bổ sung ngoài phần Constraints.
  • Mỗi test có giá trị điểm.

Example

Test 1

Input

12
1 4
1 1
1 4
3 4
4 3
5 4
6 1
2 4
3 4
4 2
2 1
4 1

Output

2
4
1
4
2
4
4

Giải thích: Sau ba lệnh chèn, đa tập là , nên hạng của là , phần tử nhỏ thứ là , tiền nhiệm của là và kế nhiệm của là . Xóa lần lượt một bản sao của rồi giá trị làm các truy vấn còn lại cho kết quả .

Lời giải tóm tắt
  • Ý tưởng: Mỗi nút lưu key, số bản sao cnt, kích thước cây con sz và priority ngẫu nhiên. Tính chất BST áp dụng cho key; tính chất heap áp dụng cho priority.
  • Ý tưởng: Chèn: nếu khóa đã có, tăng cnt; nếu chưa có, chèn nút mới theo priority, dùng splitLess khi nút mới phải trở thành gốc cây con.
  • Ý tưởng: Xóa: giảm cnt; khi cnt về 0, ghép hai cây con bằng merge.
  • Ý tưởng: rank(x) = countLess(x)+1.
  • Ý tưởng: kth(k) so sánh k với kích thước cây con trái và cnt của nút.
  • Ý tưởng: Tiền nhiệm/kế nhiệm đi xuống cây như tìm kiếm BST, đồng thời giữ ứng viên tốt nhất.
  • Ý tưởng: Sau mọi thay đổi, pull cập nhật sz, vì vậy order statistics luôn đúng.
  • Chứng minh đúng: Bất biến BST bảo đảm thứ tự duyệt giữa là thứ tự không giảm của đa tập; cnt biểu diễn chính xác số lần xuất hiện. splitLess(t,x) phân hoạch toàn bộ khóa thành <x và >=x, còn merge chỉ ghép hai cây đã có mọi khóa bên trái không lớn hơn khóa bên phải, nên cả hai phép đều bảo toàn BST. So sánh priority trong chèn/ghép bảo toàn heap-property. Do sz bằng tổng kích thước trái, số bản sao tại nút và kích thước phải, công thức rank và kth đúng theo định nghĩa thứ tự. Các bước predecessor/successor chỉ bỏ đi nhánh không thể chứa đáp án tốt hơn, nên ứng viên cuối là đáp án gần x nhất.
  • Độ phức tạp: Kỳ vọng O(log n) cho mỗi thao tác, O(n) bộ nhớ.