Cerinta completa

Given a rooted tree of nodes, where each node is uniquely numbered in between [1..N]. The node 1 is the root of the tree. Each node has an integer value which is initially 0.

You need to perform the following two kinds of queries on the tree:

  • add t value: Add value to all nodes in subtree rooted at t
  • max a b: Report maximum value on the path from a to b

Input Format

First line contains N, number of nodes in the tree. Next N-1 lines contain two space separated integers x and y which denote that there is an edge between node x and node y.
Next line contains Q, the number of queries to process.
Next Q lines follow with either add or max query per line.

Constraints




Output Format

For each max query output the answer in a separate line.

Sample Input

5
1 2
2 3
2 4
5 1
6
add 4 30
add 5 20
max 4 5
add 2 -20
max 4 5
max 3 4

Sample Output

30
20
10

Explanation

In the test case we have the following tree:

Initially all node values are zero.
Queries are performed in the following way:

add 4 30 // add 30 to node 4
add 5 20 // add 20 to node 5
max 4 5 // maximum of nodes 4,2,1,5 is 30
add 2 -20 // subtract 20 from nodes 2,3,4
max 4 5 // maximum of nodes 4,2,1,5 is 20
max 3 4 // maximum of nodes 3,2,4 is 10


Limbajul de programare folosit: cpp14

Cod:

#include <bits/stdc++.h>
using namespace std;

#define repu(i, a, b) for (int i = (a); i < (b); ++i)
#define repd(i, a, b) for (int i = (a); i > (b); --i)
#define mem(a, x) memset(a, x, sizeof(a))
#define all(a) a.begin(), a.end()
#define uni(a) a.erase(unique(all(a)), a.end())
#define count_bits(x) __builtin_popcount(x)
#define count_bitsll(x) __builtin_popcountll(x)
#define least_bits(x) __builtin_ffs(x)
#define least_bitsll(x) __builtin_ffsll(x)
#define most_bits(x) 32 - __builtin_clz(x)
#define most_bitsll(x) 64 - __builtin_clz(x)

vector<string> split(const string &s, char c) {
    vector<string> v;
    stringstream ss(s);
    string x;
    while (getline(ss, x, c)) v.push_back(x);
    return v;
}

#define error(args...) { vector<string> _v = split(#args, ','); err(_v.begin(), args); }

void err(vector<string>::iterator it) {}

template<typename T, typename... Args>
void err(vector<string>::iterator it, T a, Args... args) {
    cerr << it -> substr((*it)[0] == ' ', it -> length()) << " = " << a << 'n';
    err(++it, args...);
}

typedef long long ll;
const int MOD = 1000000007;

template<class T> inline T tmin(T a, T b) {return (a < b) ? a : b;}
template<class T> inline T tmax(T a, T b) {return (a > b) ? a : b;}
template<class T> inline void amax(T &a, T b) {if (b > a) a = b;}
template<class T> inline void amin(T &a, T b) {if (b < a) a = b;}
template<class T> inline T tabs(T a) {return (a > 0) ? a : -a;}
template<class T> T gcd(T a, T b) {while (b != 0) {T c = a; a = b; b = c % b;} return a;}

#define MAX_LOG 19
#define MAXN 100005

int n;
vector<int> G[MAXN];

/* HLD */
int chain_head[MAXN], pos_base[MAXN], chain_index[MAXN], end_sub[MAXN];
int ptr, num_chain;
/* LCA */
int par[MAX_LOG][MAXN], depth[MAXN], subtree[MAXN];
/* ST */
struct node {
    int maxi, lazy;
} st[MAXN * 4];



/* LCA */
void dfs(int v, int p, int d) {
    par[0][v] = p;
    depth[v] = d;
    subtree[v] = 1;
    repu(i, 0, G[v].size()) {
        if (G[v][i] != p) {
            dfs(G[v][i], v, d + 1);
            subtree[v] += subtree[G[v][i]];
        }
    }
}

void init() {
    dfs(1, -1, 0);
    for (int k = 0; k + 1 < MAX_LOG; ++k) {
        for (int v = 1; v <= n; ++v) {
            if (par[k][v] < 0) par[k + 1][v] = -1;
            else par[k + 1][v] = par[k][par[k][v]];
        }
    }
}

int lca(int u, int v) {
    if (depth[u] > depth[v]) swap(u, v);
    for (int k = 0; k < MAX_LOG; ++k) {
        if ((depth[u] - depth[v]) >> k & 1) {
            v = par[k][v];
        }
    }
    if (u == v) return u;
    for (int k = MAX_LOG - 1; k >= 0; --k) {
        if (par[k][u] != par[k][v]) {
            u = par[k][u];
            v = par[k][v];
        }
    }
    return par[0][u];
}

/* Segment tree */
inline void lazy_eval(int ind, int len) {
    if (st[ind].lazy != 0) {
        st[ind].maxi += st[ind].lazy;
        if (len > 1) {
            int c1 = ind << 1, c2 = c1 | 1;
            st[c1].lazy += st[ind].lazy;
            st[c2].lazy += st[ind].lazy;
        }
        st[ind].lazy = 0;
    }
}

void build_tree(int ind, int s, int e) {
    if(s == e - 1) {
        st[ind].maxi = st[ind].lazy = 0;
        return;
    }
    int c1 = ind << 1, c2 = c1 | 1, m = (s + e) >> 1;
    build_tree(c1, s, m);
    build_tree(c2, m, e);
    st[ind].maxi = tmax(st[c1].maxi, st[c2].maxi);
    st[ind].lazy = 0;
}

void update_tree(int ind, int s, int e, int ss, int ee, int val) {
    lazy_eval(ind, e - s);
    if (s >= ee || e <= ss) return;
    if (s >= ss && e <= ee) {
        st[ind].lazy += val;
        lazy_eval(ind, e - s);
        return;
    }
    int c1 = ind << 1, c2 = c1 | 1, m = (s + e) >> 1;
    update_tree(c1, s, m, ss, ee, val);
    update_tree(c2, m, e, ss, ee, val);
    st[ind].maxi = tmax(st[c1].maxi, st[c2].maxi);
}

int query_tree(int ind, int s, int e, int ss, int ee) {
    lazy_eval(ind, e - s);
    if (s >= ee || e <= ss) return INT_MIN;
    if (s >= ss && e <= ee) return st[ind].maxi;
    int c1 = ind << 1, c2 = c1 | 1, m = (s + e) >> 1;
    int vl = query_tree(c1, s, m, ss, ee);
    int vr = query_tree(c2, m, e, ss, ee);
    st[ind].maxi = tmax(st[c1].maxi, st[c2].maxi);
    return tmax(vl, vr);
}

/* Heavy light decomposition */
void build_hld(int u) {
    if(chain_head[num_chain] == -1) chain_head[num_chain] = u;
    chain_index[u] = num_chain;
    pos_base[u] = ptr++;
    
    int most = 0, dem = -1;
    repu(i, 0, G[u].size()) {
        int v = G[u][i];
        if (v != par[0][u]) {
            if (subtree[v] > most) {
                most = subtree[v];
                dem = v;
            }
        }
    }
    if (dem != -1) build_hld(dem);
    repu(i, 0, G[u].size()) {
        int v = G[u][i];
        if (v != par[0][u] && v != dem) {
            ++num_chain;
            build_hld(v);
        }
    }
    end_sub[u] = ptr;
}

/* query on path u -> v */
int query_hld(int u, int v) {
    int ans = INT_MIN;
    int uchain, vchain = chain_index[v];
    /* interval [x, y) */
    while (1) {
        uchain = chain_index[u];
        if (uchain != vchain) {
            int tmp = query_tree(1, 0, ptr, pos_base[chain_head[uchain]], pos_base[u] + 1);
            /* process something here */
            amax(ans, tmp);
            u = chain_head[uchain];
            u = par[0][u];
        }
        else {
            int tmp = query_tree(1, 0, ptr, pos_base[v], pos_base[u] + 1);
            /* process something here */
            amax(ans, tmp);
            break;
        }
    }
    return ans;
}

/* update value on path u -> v */
void update_hld(int v, int val) {
    int s = pos_base[v], e = end_sub[v];
    update_tree(1, 0, ptr, s, e, val);
}


int main(int argc, char *argv[]) {
    ios_base::sync_with_stdio(false);
    int q, a, b;
    string op;

    mem(chain_head, -1);
    ptr = num_chain = 0;

    cin >> n;
    repu(i, 1, n) {
        cin >> a >> b;
        G[a].push_back(b); G[b].push_back(a);
    }

    init();
    build_hld(1);
    build_tree(1, 0, n);

    cin >> q;
    repu(i, 0, q) {
        cin >> op >> a >> b;
        if (op[0] == 'a') update_hld(a, b);
        else {
            int p = lca(a, b);
            int res = query_hld(a, p);
            amax(res, query_hld(b, p));
            printf("%d\n", res);
        }
    }

    return 0;
}

Scor obtinut: 1.0

Submission ID: 464653781

Link challenge: https://www.hackerrank.com/challenges/subtrees-and-paths/problem

Subtrees And Paths