Duy trì một mảng số qua hai loại thao tác: đảo một đoạn [a,b] và tính tổng các phần tử trong đoạn đó.
Mỗi truy vấn có dạng tab, với chỉ số đánh từ 1:
1ab: đảo thứ tự đoạn a,…,b;
2ab: in tổng các phần tử trong đoạn a,…,b.
Input
Dòng đầu chứa nm. Dòng thứ hai chứa n phần tử ban đầu. Mỗi dòng trong số m dòng tiếp theo chứa tab.
Output
Với mỗi truy vấn loại 2, in tổng đoạn được hỏi.
Constraints
1≤n≤2⋅105,1≤m≤105.
0≤ai≤109; tổng đoạn có thể cần số nguyên 64-bit.
Scoring
Subtask small: 50 điểm, gồm 10 test nhỏ.
Subtask full: 50 điểm, gồm 10 test không có giới hạn bổ sung ngoài phần Constraints.
Mỗi test có giá trị 5 điểm.
Example
Test 1
Input
6 5
2 1 4 0 3 5
2 1 3
1 2 5
2 2 4
1 1 6
2 4 6
Output
7
7
5
Giải thích: Tổng ba phần tử đầu ban đầu là 7; sau khi đảo 2,…,5, dãy thành [2,3,0,4,1,5] nên tổng 2,…,4 cũng là 7. Đảo toàn dãy tạo [5,1,4,0,3,2], và tổng 4,…,6 bằng 5.
Lời giải tóm tắt
Ý tưởng: Mỗi nút lưu tổng cây con. Với mọi truy vấn, split thành L, M=[a,b], R. Nếu loại 1, bật rev trên M. Nếu loại 2, đáp án là M->sum. Sau đó luôn merge ba đoạn về lại. Reverse không thay đổi tổng nên không cần sửa sum khi bật cờ; chỉ cần đổi hai con và truyền cờ đúng lúc.
Chứng minh đúng:pull duy trì tổng bằng tổng trái + giá trị nút + tổng phải, nên aggregate đúng bằng quy nạp theo cây. Split cô lập chính xác các chỉ số cần hỏi; vì vậy tổng của M là tổng đoạn. Phép đảo chỉ hoán vị phần tử trong M, không đổi tổng và cờ rev bảo đảm thứ tự logic đúng. Merge bảo toàn thứ tự nối đoạn, nên bất biến mảng được khôi phục sau truy vấn.
Độ phức tạp: Kỳ vọng O(log n) mỗi thao tác; O(n) bộ nhớ.