canuc80k1609·10/50

Cộng Đoạn, Tính Tổng

Nộp bài trên LQDOJ

Bài 16 · Fenwick Tree

Input gồm nhiều test độc lập. Trong mỗi test có một mảng gồm phần tử, ban đầu tất cả đều bằng .

Bạn cần xử lý thao tác theo thứ tự:

  • : cộng vào mọi phần tử ;
  • : tính tổng .

Khi chuyển sang test mới, mọi dữ liệu của test trước bị bỏ và mảng lại bắt đầu từ toàn số .

Input

  • Dòng đầu chứa số nguyên , số lượng test.
  • Mỗi test bắt đầu bằng một dòng chứa hai số nguyên và , sau đó là dòng thao tác theo một trong hai dạng trên.

Output

  • Với mỗi thao tác loại của mọi test, in tổng được hỏi trên một dòng theo đúng thứ tự xuất hiện.

Constraints

  • .
  • Trong mỗi test: .
  • .
  • Với thao tác loại : .
  • Mọi giá trị tích lũy và tổng đều nằm trong miền của số nguyên có dấu -bit.

Scoring

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

Example

Test 1

Input

2
5 5
1 1 5
0 2 4 3
1 1 3
0 1 2 2
1 2 5
4 4
0 1 4 1
0 2 3 4
1 1 4
1 2 2

Output

0
6
11
12
5

Giải thích: Ở test đầu, sau hai cập nhật mảng là , nên tổng đoạn bằng . Test thứ hai bắt đầu lại từ ; hai cập nhật tạo mảng , cho các tổng và .

Lời giải tóm tắt
  • Phân tích: Với mảng hiệu d, cộng v trên [l,r] tạo hai sự kiện: d[l]+=v và d[r+1]-=v. Để lấy tổng đoạn chứ không chỉ giá trị tại một điểm, ta dùng hai Fenwick.
  • Phân tích: Gọi B1 lưu các hệ số của sự kiện và B2 lưu hệ số đã nhân với vị trí. Khi thêm một sự kiện (p,x), cập nhật:
  • Phân tích: B1[p] += x;
  • Phân tích: B2[p] += x·(p-1).
  • Phân tích: Khi đó tổng của mảng trên tiền tố 1..t là
  • Phân tích: P(t) = t·B1.prefix(t) - B2.prefix(t).
  • Thuật toán: Với mỗi test, tạo mới hai Fenwick rỗng.
  • Thuật toán: Cập nhật 0 l r v: thêm sự kiện (l,+v) và, nếu r<n, sự kiện (r+1,-v) vào cả hai Fenwick theo công thức trên.
  • Thuật toán: Truy vấn 1 l r: in P(r)-P(l-1).
  • Chứng minh: Xét một sự kiện (p,x). Nó làm mọi phần tử từ p trở đi tăng thêm x. Trong tiền tố 1..t với t≥p, sự kiện đóng góp cho đúng t-p+1 phần tử, tức x(t-p+1)=xt-x(p-1). Hai Fenwick tạo đúng giá trị này qua biểu thức t·B1.prefix(t)-B2.prefix(t); nếu t<p, sự kiện chưa nằm trong tiền tố nên đóng góp 0.
  • Chứng minh: Một cập nhật đoạn là tổng của sự kiện bắt đầu +v tại l và sự kiện kết thúc -v tại r+1, nên công thức tính đúng tổng tiền tố sau mọi cập nhật. Lấy hiệu hai tiền tố loại bỏ phần trước l và cho đúng tổng trên [l,r]. Mỗi test khởi tạo cấu trúc mới, vì vậy các test không ảnh hưởng lẫn nhau.
  • Độ phức tạp: Mỗi thao tác mất O(log n) thời gian. Mỗi test dùng O(n) bộ nhớ; tổng thời gian là O(Σ q log n) trên toàn input.