Hướng dẫn giải của Trò Chơi Bài (Platinum)
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.
Lời giải: Trò Chơi Bài Hai Luật
Hướng tiếp cận
Bài toán yêu cầu tìm điểm tối đa khi người A có thể đổi từ "bài cao thắng" sang "bài thấp thắng" đúng một lần ở bất kỳ vòng nào.
Gọi điểm đổi luật là sau vòng (với , nghĩa là đổi luật ngay từ đầu). Khi đó:
- vòng đầu (vòng 1 đến ): luật "bài cao thắng".
- vòng sau (vòng đến ): luật "bài thấp thắng".
Đáp án =
trong đó:
- = số điểm tối đa người A giành được trong vòng đầu với luật "bài cao thắng", dùng lá bài cao nhất của mình.
- = số điểm tối đa người A giành được trong vòng cuối với luật "bài thấp thắng", dùng lá bài thấp nhất của mình.
Nhận xét quan trọng
Phân chia bài tối ưu: Trong đoạn "bài cao thắng", người A nên dùng lá bài lớn nhất; trong đoạn "bài thấp thắng", nên dùng lá bài nhỏ nhất. Đây là vì không có lý gì dùng một lá bài nhỏ để cố đánh bại ở đoạn cao-thắng khi đã có bài lớn hơn.
Tính prefix: Với vòng đầu (người B đánh ) và lá bài lớn nhất của người A, dùng chiến lược tham lam: dùng lá bài nhỏ nhất lớn hơn lá của B (nếu có).
Tính suffix: Với vòng cuối (người B đánh theo thứ tự ngược) và lá bài nhỏ nhất của người A (theo thứ tự ngược), dùng chiến lược đối xứng.
Thuật toán
Để tính và hiệu quả, ta dùng Segment Tree trên không gian lá bài .
Cấu trúc nút Segment Tree:
covers: số lá bài của người A trong đoạn này chưa được sử dụng (lá bài có thể "che" bài của B).coverables: số lá bài của người B trong đoạn này chưa được "che".points: số điểm đã ghi nhận trong đoạn này.
Kết hợp hai nút (trái , phải ):
ep = min(x.coverables, y.covers) // bài B phía trái được che bởi bài A phía phải
points = x.points + y.points + ep
covers = x.covers + y.covers - ep
coverables = x.coverables + y.coverables - ep
Tính prefix[i]:
- Lấy lá bài lớn nhất của người A (đây là những lá bài không thuộc dãy B, theo thứ tự giảm dần).
- Với : chèn lá bài vào vị trí tương ứng trong segment tree (gắn
coverables = 1), đồng thời chèn lá bài lớn thứ của người A (gắncovers = 1). Sau mỗi bước, .
Tính suffix[i]: Làm tương tự nhưng theo chiều ngược (vòng cuối trước, luật thấp thắng). Đổi biến: thay mỗi lá bài bằng để quy về bài "thấp thắng" thành "cao thắng". Dùng lá bài nhỏ nhất của người A, xử lý từ vòng ngược về .
Kết quả:
Độ phức tạp
- Thời gian: — mỗi thao tác chèn vào segment tree mất , thực hiện lần cho cả prefix và suffix.
- Bộ nhớ: .
Bình luận