canuc80k5816·17/50

Ghép Hàm Trên Đường

Nộp bài trên LQDOJ

Bài 58 · Heavy Light Decomposition

Đặt . Cho một cây gồm đỉnh, đánh số từ đến . Tại đỉnh có hàm affine

Bạn cần xử lý thao tác:

  • : thay hàm tại đỉnh bằng ;
  • : đi theo đường đơn từ đến , lần lượt áp dụng hàm tại từng đỉnh vào giá trị hiện tại. Hàm tại được áp dụng đầu tiên và hàm tại được áp dụng cuối cùng. In giá trị thu được modulo .

Cả hai đầu mút của đường đều được tính. Vì phép hợp hàm không giao hoán, thứ tự từ đến là một phần của truy vấn.

Input

  • Dòng đầu chứa hai số nguyên và .
  • Mỗi dòng trong dòng tiếp theo chứa hai số nguyên và , mô tả hàm ban đầu tại đỉnh , theo thứ tự .
  • Mỗi dòng trong dòng tiếp theo chứa hai số nguyên và , biểu diễn một cạnh của cây.
  • Mỗi dòng trong dòng cuối có một trong hai dạng hoặc .

Output

  • Với mỗi thao tác loại , in kết quả của phép áp dụng tuần tự, mỗi đáp án trên một dòng.

Constraints

  • ;
  • ;
  • ;
  • ;
  • ;
  • các cạnh tạo thành một cây.

Scoring

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

Example

Test 1

Input

5 8
2 1
3 0
1 4
2 2
5 1
0 1
0 2
1 3
1 4
1 3 2 1
1 2 3 2
0 1 1 5
1 3 2 1
1 4 3 0
0 0 1 0
1 2 4 3
1 0 0 10

Output

29
80
23
14
61
10

Giải thích: Với truy vấn đầu, đường là ; giá trị lần lượt biến thành , rồi . Sau khi hàm tại đỉnh được đổi thành , cùng đường đó biến thành , rồi .

Lời giải tóm tắt
  • 1. Biểu diễn phép hợp: Một hàm affine được lưu bằng cặp (a,b), nghĩa là f(x)=a·x+b (mod MOD). Gọi concatenate(f,g) là hàm nhận được khi áp dụng f trước rồi áp dụng g:
  • 1. Biểu diễn phép hợp:

text g(f(x)) = (g.a · f.a) x + (g.a · f.b + g.b) (mod MOD). - 1. Biểu diễn phép hợp: Phép hợp hàm có tính kết hợp nhưng không giao hoán, vì vậy thứ tự trên đường phải được giữ nguyên. - 2. Thông tin trong segment tree: Mỗi node lưu hai hàm: - 2. Thông tin trong segment tree: forward: hợp các hàm từ trái sang phải trong đoạn; - 2. Thông tin trong segment tree: backward: hợp các hàm từ phải sang trái. - 2. Thông tin trong segment tree: Khi ghép đoạn trái L với đoạn phải R: - 2. Thông tin trong segment tree:

text forward = concatenate(L.forward, R.forward) backward = concatenate(R.backward, L.backward) - 2. Thông tin trong segment tree: Đảo hướng một đoạn chỉ cần đổi chỗ forward và backward. Cập nhật loại 0 là point set tại vị trí HLD của đỉnh. - 3. Truy vấn đường có hướng: Heavy-Light Decomposition tách đường u→v thành O(log n) đoạn. Ta dùng hai biến tích lũy: một biến nối các đoạn lấy từ phía u, một biến chèn các đoạn lấy từ phía v về đúng đầu. Những đoạn đi từ dưới lên được đảo bằng trường backward. - 3. Truy vấn đường có hướng: Sau khi nối toàn bộ, forward chính là hàm tổng hợp theo thứ tự từ u đến v. Với cặp (A,B), đáp án là (A·x+B) mod MOD. - 4. Đúng đắn và độ phức tạp: Mỗi node segment tree mô tả đúng phép hợp theo cả hai hướng nhờ tính kết hợp của hợp hàm. Quy trình HLD ghép đúng thứ tự từng đỉnh trên đường nên hàm cuối trùng với việc áp dụng tuần tự theo đề. Point set mất O(log n); path query mất O(log² n); bộ nhớ O(n).