Cho một cây gồm n đỉnh, đánh số từ 1 đến n. Cây được chọn gốc tại đỉnh r; vì vậy, khái niệm cây con trong bài luôn được hiểu theo gốc này. Mỗi đỉnh i có một giá trị nguyên không âm ban đầu ai.
Bạn cần xử lý lần lượt m thao tác thuộc bốn loại:
1xyz: cộng z vào giá trị của mọi đỉnh trên đường đơn từ x đến y, kể cả hai đầu mút;
2xy: tính tổng giá trị của mọi đỉnh trên đường đơn từ x đến y;
3xz: cộng z vào giá trị của mọi đỉnh thuộc cây con gốc x, kể cả x;
4x: tính tổng giá trị của mọi đỉnh thuộc cây con gốc x, kể cả x.
Với thao tác loại 2 và 4, chỉ cần in phần dư của tổng khi chia cho p. Các phép cộng cũng có thể được lưu theo mô-đun p, vì điều này không làm thay đổi bất kỳ kết quả cần in nào. Đặc biệt, nếu p=1 thì mọi kết quả đều bằng
0.
Input
Dòng đầu chứa bốn số nguyên n,m,r và p.
Dòng thứ hai chứa n số nguyên a1,a2,…,an.
Mỗi dòng trong n−1 dòng tiếp theo chứa hai số nguyên u và v, mô tả một cạnh của cây.
Mỗi dòng trong m dòng cuối mô tả một thao tác theo một trong bốn dạng đã nêu.
Output
Với mỗi thao tác loại 2 hoặc 4, in đáp án theo mô-đun p trên một dòng riêng. Mỗi đáp án nằm trong đoạn từ 0 đến p−1.
Constraints
1≤n,m≤105.
1≤r≤n.
1≤p≤230.
0≤ai≤2.147483647⋅109.
Trong thao tác loại 1 hoặc 3: 1≤z≤2.147483647⋅109.
Mọi chỉ số đỉnh xuất hiện trong thao tác đều thuộc đoạn 1,…,n.
n−1 cạnh tạo thành một cây vô hướng.
Scoring
Subtask 1 (50% số điểm): n,m≤40.
Subtask 2 (50% số điểm): Không có giới hạn bổ sung.
Giải thích: Gốc của cây là 3, nên cây con của 4 gồm các đỉnh 4,5,6, còn cây con của 1 gồm 1,2. Sau từng phép cộng, các tổng tương ứng có phần dư lần lượt là 0,3,8,4,6 và 3 khi chia cho 10.
Lời giải tóm tắt
Mô hình: Ta cần đồng thời biến đường bất kỳ và cây con thành các đoạn liên tiếp của một mảng. Heavy-Light Decomposition giải quyết phần đường; thứ tự heavy-first còn bảo đảm toàn bộ cây con của u nằm trong đoạn [pos[u], pos[u] + size[u] - 1].
Thuật toán: Dựng HLD với đúng gốc r để tính parent, depth, size, heavy, head và pos. Đặt giá trị của đỉnh u tại base[pos[u]]. Trên mảng này, xây segment tree lazy hỗ trợ cộng đoạn và tổng đoạn theo mô-đun p.
Thuật toán: Loại 1 và 2: tách đường thành O(log n) đoạn HLD rồi lần lượt cộng hoặc lấy tổng các đoạn.
Thuật toán: Loại 3 và 4: dùng duy nhất đoạn cây con [pos[x], pos[x]+size[x]-1].
Thuật toán: Mỗi lazy cộng z vào đoạn dài len làm tổng tăng z*len; phép nhân dùng số nguyên 64 bit rồi lấy modulo.
Chứng minh đúng: Vòng phân rã HLD chia mỗi đường thành các đoạn rời nhau, hợp lại đúng bằng mọi đỉnh trên đường, nên thao tác đường tác động và tính tổng mỗi đỉnh đúng một lần. Duyệt heavy-first hoàn tất toàn bộ hậu duệ của một đỉnh trước khi rời cây con, vì vậy đúng size[x] vị trí liên tiếp bắt đầu tại pos[x] biểu diễn cây con của x theo gốc r. Segment tree lazy thực hiện chính xác phép cộng và tổng trên các đoạn đó. Do phép cộng và lấy tổng tương thích với phép lấy dư, mọi kết quả in ra đúng modulo p.
Độ phức tạp: Tiền xử lý O(n). Thao tác cây con tốn O(log n), thao tác đường tốn O(log^2 n). Bộ nhớ O(n).