Các lượt nộp
    Danh sách bài
    Trang chủ
    Báo lỗi

    solution

    Đề bài: [Trình biên dịch] Đếm tham chiếu có lan truyền (Cascading Reference Counting)

    Trong thực tế, một đối tượng thường chứa các trường trỏ tới đối tượng khác. Khi một đối tượng bị giải phóng, nó phải giảm refcount của TẤT CẢ các đối tượng con mà nó tham chiếu — có thể kéo theo một dây chuyền giải phóng khác (cascading free).

    Xét nnn biến gốc (root) đánh số 1..n1..n1..n, ban đầu tất cả NULL. Có qqq câu lệnh:

    • NEW v x m c_1 c_2 ... c_m: tạo đối tượng mới định danh x (số nguyên dương chưa từng xuất hiện) có mmm trường, trỏ lần lượt tới các đối tượng ĐANG TỒN TẠI c1,…,cmc_1,\dots,c_mc1​,…,cm​ (refcount của mỗi cic_ici​ tăng 1 do trường này), sau đó gán biến gốc v trỏ tới x (refcount(x) tăng 1 do gán gốc). Nếu v trước đó trỏ tới đối tượng y, refcount(y) giảm 1.
    • SET v x: gán biến gốc v trỏ tới đối tượng ĐANG TỒN TẠI x (refcount(x) tăng 1 TRƯỚC), sau đó refcount đối tượng cũ của v (nếu có) giảm 1.
    • CLEAR v: gán v = NULL; refcount đối tượng cũ (nếu có) giảm 1.

    Mỗi khi refcount của một đối tượng ooo giảm về 000: ooo bị giải phóng; ngay sau đó, với MỖI trường (con) của ooo, refcount của con giảm 1 theo — nếu con nào cũng về 000 thì lại tiếp tục giải phóng dây chuyền. Khi lan truyền, xét các con theo thứ tự định danh TĂNG DẦN, và xử lý theo cơ chế hàng đợi FIFO (đối tượng được xác định giải phóng trước được xử lý lan truyền trước đối tượng được thêm vào sau).

    Đề bảo đảm đồ thị tham chiếu tĩnh cha→con (hình thành khi NEW) không có chu trình (là DAG), và mọi đối tượng được tham chiếu trong cic_ici​ hoặc trong SET đảm bảo tại thời điểm đó ĐANG TỒN TẠI (đã tạo và chưa bị giải phóng).

    Ví dụ: n=1n=1n=1, lệnh NEW 1 1 0 (tạo đối tượng 1, không con), NEW 1 2 1 1 (tạo đối tượng 2 có con là đối tượng 1, root 1 chuyển sang trỏ đối tượng 2), CLEAR 1. Khi CLEAR 1, đối tượng 2 về refcount 000 nên bị giải phóng, kéo theo refcount đối tượng 1 giảm về 000 nên cũng bị giải phóng. Thứ tự giải phóng: 2 1.

    • Định dạng đầu vào:

      Dòng đầu: hai số nguyên nnn, qqq (1≤n≤10001 \le n \le 10001≤n≤1000, 0≤q≤20000 \le q \le 20000≤q≤2000; tổng số phần tử cic_ici​ xuất hiện trong toàn bộ input không vượt quá 500050005000). qqq dòng tiếp theo, mỗi dòng là NEW v x m c_1 ... c_m, SET v x hoặc CLEAR v.

    • Định dạng đầu ra:

      In 2 dòng như bài đếm tham chiếu cơ bản:

      • Dòng 1: danh sách định danh bị giải phóng theo đúng thứ tự lan truyền thực tế trong toàn bộ chương trình, cách nhau dấu cách (trống nếu không có).
      • Dòng 2: danh sách định danh còn sống (refcount >0>0>0) ở cuối, tăng dần, cách nhau dấu cách (trống nếu không còn).

      Với ví dụ trên, kết quả là:

      2 1
      
      

    Ví dụ:

    Đầu vào:

    1 3
    NEW 1 1 0
    NEW 1 2 1 1
    CLEAR 1

    Đầu ra:

    2 1
    
    

    Đầu vào:

    2 2
    NEW 1 5 0
    NEW 2 6 0

    Đầu ra:

    
    5 6
    

    Đang tải editor...