canuc80k1714·15/50

Cộng, Gán Và Lấy Tổng

Nộp bài trên LQDOJ

Bài 1.8 · Segment Tree

Cho mảng gồm số nguyên. Bạn cần xử lý các thao tác trên đoạn đóng :

  1. cộng vào mọi phần tử;
  2. gán mọi phần tử bằng ;
  3. tính tổng các phần tử.

Các thao tác có hiệu lực theo đúng thứ tự xuất hiện. Đặc biệt, phép gán ghi đè mọi giá trị được tạo bởi các thao tác trước đó trên đoạn tương ứng.

Input

  • Dòng đầu chứa hai số nguyên và .
  • Dòng thứ hai chứa số nguyên .
  • Mỗi dòng trong dòng tiếp theo có một trong ba dạng:
  • : cộng vào đoạn ;
  • : gán đoạn bằng ;
  • : hỏi tổng đoạn .

Output

  • Với mỗi thao tác loại , in một dòng chứa tổng cần tìm.

Constraints

  • .
  • .
  • .
  • Dùng số nguyên -bit cho tổng và giá trị trung gian.

Scoring

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

Example

Test 1

Input

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

Output

15
23
12
17

Giải thích: Sau phép cộng đầu tiên mảng là ; phép gán tiếp theo đưa ba phần tử cuối về . Các tổng được tính trên đúng trạng thái hiện tại.

Lời giải tóm tắt
  • Phân tích: Mỗi node lưu tổng đoạn. Lazy state gồm một tag gán tùy chọn và một tag cộng. Phép gán có quyền ưu tiên: khi gán toàn node, tổng trở thành X * độ_dài, tag gán được thay bằng X và tag cộng cũ phải xóa. Khi cộng, tăng tổng; nếu node đang có tag gán thì tăng chính giá trị gán, ngược lại cộng vào tag cộng.
  • Thuật toán: Xây Segment Tree. Trước khi đi xuống, đẩy tag gán rồi tag cộng sang hai con. Range update áp dụng trực tiếp ở node phủ trọn; range query cộng tổng từ các node giao đoạn.
  • Chứng minh tính đúng đắn: Các hàm apply_set và apply_add biến tổng node đúng như thao tác trên từng phần tử và lưu một biểu diễn tương đương của chuỗi thao tác chưa đẩy. Quy tắc gán xóa cộng cũ, còn cộng sau gán tăng giá trị gán, nên thứ tự thời gian được bảo toàn. Merge cộng tổng hai đoạn rời nhau. Vì vậy mọi node luôn lưu đúng tổng và query trả đúng tổng đoạn.
  • Độ phức tạp: Xây O(N), mỗi thao tác O(log N), bộ nhớ O(N).