canuc80k7415·16/50

Kiểm Tra Hai Màu Theo Ngày

Nộp bài trên LQDOJ

Bài 74 · Rollback

Có đỉnh được đánh số từ đến . Ban đầu đồ thị vô hướng không có cạnh. Trong mỗi ngày, đúng một cặp đỉnh u,v được đưa ra:

  • nếu cạnh chưa tồn tại thì cạnh đó được thêm vào;
  • nếu cạnh đang tồn tại thì cạnh đó bị xóa.

Sau khi thực hiện thay đổi của ngày hiện tại, hãy xác định liệu có thể tô mỗi đỉnh bằng một trong hai màu sao cho hai đầu mút của mọi cạnh luôn khác màu hay không.

Input

  • Dòng đầu chứa hai số nguyên và .
  • Mỗi trong dòng tiếp theo chứa hai số nguyên , mô tả cạnh được đổi trạng thái trong ngày tương ứng.

Output

  • Sau mỗi ngày, in YES nếu đồ thị hiện tại có thể tô bằng hai màu; ngược lại in NO.

Constraints

  • .
  • .

Scoring

  • Subtask ( số điểm): .
  • Subtask ( số điểm): Không có giới hạn bổ sung.

Example

Test 1

Input

4 7
1 2
2 3
1 3
1 3
3 4
1 4
2 4

Output

YES
YES
NO
YES
YES
YES
NO

Giải thích: Ba cạnh đầu tạo tam giác nên ngày thứ ba có đáp án NO; xóa cạnh làm đồ thị lại tô được hai màu. Ở ngày cuối, ba đỉnh tạo một tam giác mới nên đáp án trở thành NO.

Lời giải tóm tắt
  • Phân tích: Một cạnh được bật ở một ngày và bị tắt ở lần xuất hiện kế tiếp của chính cặp đỉnh đó. Vì vậy mỗi cạnh hoạt động trên một hoặc nhiều khoảng thời gian nửa mở [l,r). Ta cần kiểm tra tính hai phía của đồ thị ở từng thời điểm nhưng không thể thêm rồi xóa trực tiếp bằng DSU thường.
  • Thuật toán: Ghép các lần xuất hiện liên tiếp của từng cạnh để thu được mọi khoảng sống; cạnh còn bật tới cuối có mốc phải bằng q. Phân rã mỗi khoảng vào cây đoạn trên trục thời gian.
  • Thuật toán: Khi DFS cây đoạn, dùng DSU rollback có parity. Với mỗi đỉnh, parity[x] là màu tương đối giữa x và cha DSU. Thêm cạnh u-v tương đương áp ràng buộc màu của hai đỉnh khác nhau. Nếu hai đỉnh đã cùng gốc mà parity hiện tại bằng nhau, ràng buộc gây mâu thuẫn; biến bad tăng một. History lưu cả phép gộp lẫn lần tăng bad, nên khi rời nút ta rollback chính xác về snapshot.
  • Thuật toán: Ở lá thời gian t, in YES khi bad=0, ngược lại in NO.
  • Chứng minh tính đúng: Mỗi cạnh được đặt vào đúng các nút cây đoạn có hợp đoạn bằng khoảng nó đang tồn tại. Do đó, trên đường từ gốc tới lá t, DSU nhận đúng và đủ các cạnh của đồ thị sau ngày t.
  • Chứng minh tính đúng: DSU parity duy trì mọi phương trình màu khác nhau trong từng thành phần. Một cạnh nội bộ gây mâu thuẫn đúng khi parity hai đầu không thỏa điều kiện khác màu; vì bad đếm mọi ràng buộc mâu thuẫn đang hoạt động, đồ thị tô được hai màu khi và chỉ khi bad=0. Rollback khôi phục toàn bộ parent, size, parity và bad trước khi sang nhánh thời gian khác, nên kết luận đúng ở mọi lá.
  • Độ phức tạp: Mỗi khoảng cạnh xuất hiện ở O(log q) nút. Union-by-size không path compression cho độ sâu O(log n), nên thời gian O(q log q log n) và bộ nhớ O(n+q log q).