UAIC Competitive Programming

Problem 14: Persistent Segment Tree

Problem Statement: Implement a persistent segment tree to answer range sum queries over different versions of an array.

Input

First line contains n and q. Next line contains n integers. Then q queries follow. Each query: version, l, r.

Output

For each query, print the range sum for the given version.

Examples


Input:
5 3\n1 2 3 4 5\n0 1 3\n1 2 5\n0 1 5

Output:
6\n14\n15
                

Solution in C++


#include <iostream>
#include <vector>
using namespace std;

struct Node{
    int sum;
    Node *left, *right;
    Node(int sum, Node* left, Node* right): sum(sum), left(left), right(right) {}
    Node(): sum(0), left(NULL), right(NULL) {}
};

int n;

Node* build(int l, int r, vector<int>& arr){
    if(l == r) return new Node(arr[l], NULL, NULL);
    int mid = (l+r)/2;
    Node* left = build(l, mid, arr);
    Node* right = build(mid+1, r, arr);
    return new Node(left->sum + right->sum, left, right);
}

Node* update(Node* prev, int l, int r, int pos, int val){
    if(l > pos || r < pos) return prev;
    if(l==r) return new Node(val, NULL, NULL);
    int mid = (l+r)/2;
    Node* left = update(prev->left, l, mid, pos, val);
    Node* right = update(prev->right, mid+1, r, pos, val);
    return new Node(left->sum + right->sum, left, right);
}

int query(Node* root, int l, int r, int ql, int qr){
    if(ql>r || qr<l) return 0;
    if(ql<=l && r<=qr) return root->sum;
    int mid = (l+r)/2;
    return query(root->left, l, mid, ql, qr) + query(root->right, mid+1, r, ql, qr);
}

int main(){
    int q;
    cin >> n >> q;
    vector<int> arr(n);
    for(int i=0;i<n;i++) cin >> arr[i];
    vector<Node*> version;
    version.push_back(build(0, n-1, arr));
    while(q--){
        int ver, l, r;
        cin >> ver >> l >> r; // 0-indexed
        cout << query(version[ver], 0, n-1, l, r-1) << "\n";
    }
    return 0;
}