In this HackerEarth Tree queries problem solution You are given a tree T with N nodes rooted at node 1. Each node has a value A[i] associated with it.

You are required to perform Q queries where each query is of type:
  1. u x: Increment the value associated with node u by x.
  2. p: Find the shortest distance of any node from the root that has a value strictly greater than p. If no such node exists, then print -1.


HackerEarth Tree queries problem solution


HackerEarth Tree queries problem solution.

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <ctime>
#include <cassert>
#include <complex>
#include <string>
#include <cstring>
#include <chrono>
#include <random>
#include <queue>
#include <bitset>
#include <iomanip>
#include <fstream>
#include <stack>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll , ll> PLL;
typedef long double ld;

#define pb push_back
#define all(c) c.begin(),c.end()
#define allr(c) c.rbegin(),c.rend()
int mod = 1000000007;
const int inf = 1034567891;
const ll LL_INF = 1234567890123456789ll;
#define PI 3.14159265
#define endl '\n'
#define F first
#define S second
#define debug(x) cout << #x << " = " << x << endl;
#define TRACE

#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
cout << name << " : " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
const char* comma = strchr(names + 1, ',');cout.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
#else
#define trace(...)
#endif

#define out(container) for (auto it : container) cout << it << " "; cout << endl;


template < typename T > T GCD(T a, T b) { ll t; while(a) { t = a; a = b % a; b = t; } return b; }
template < typename T > string toString(T a) { return to_string(a); }
template < typename T > void toInt(string s, T &x) { stringstream str(s); str >> x;}
inline int add(int x, int y){ x += y; if(x >= mod) x -= mod; return x;}
inline int sub(int x, int y){ x -= y; if(x < 0) x += mod; return x;}
inline int mul(int x, int y){ return (x * 1ll * y) % mod;}
inline int powr(int a, ll b){
int x = 1 % mod;
while(b){
if(b & 1) x = mul(x, a);
a = mul(a, a);
b >>= 1;
}
return x;
}
inline int inv(int a){ return powr(a, mod - 2);}

const int N = 2e5 + 5;

ll t[4*N], a[N];

void build(int v, int tl, int tr) {
if (tl == tr) {
t[v] = a[tl];
} else {
int tm = (tl + tr) / 2;
build(v*2, tl, tm);
build(v*2+1, tm+1, tr);
t[v] = max(t[v*2], t[v*2+1]);
}
}
void update(int v, int tl, int tr, int pos, ll new_val) {
if (tl == tr) {
t[v] += new_val;
} else {
int tm = (tl + tr) / 2;
if (pos <= tm)
update(v*2, tl, tm, pos, new_val);
else
update(v*2+1, tm+1, tr, pos, new_val);
t[v] = max(t[v*2], t[v*2+1]);
}
}

int get_first(int v, int lv, int rv, int l, int r, ll x) {
if(lv > r || rv < l) return -1;
if(l <= lv && rv <= r) {
if(t[v] <= x) return -1;
while(lv != rv) {
int mid = lv + (rv-lv)/2;
if(t[2*v] > x) {
v = 2*v;
rv = mid;
} else {
v = 2*v+1;
lv = mid+1;
}
}
return lv;
}
int mid = lv + (rv-lv)/2;
int rs = get_first(2*v, lv, mid, l, r, x);
if(rs != -1) return rs;
return get_first(2*v+1, mid+1, rv, l ,r, x);
}

vector<int> adj[N];
bool vis[N];
int dis[N];

void dfs(int s, int d) {
vis[s] = true;
dis[s] = d;
for (auto it : adj[s]) {
if (!vis[it]) {
dfs(it, d + 1);
}
}
}

int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int tt;
cin >> tt;
assert(1 <= tt and tt <= 10);
while(tt--){
for(int i = 0 ; i < N ; i++)
{
adj[i].clear();
vis[i] = false;
dis[i] = 0;
}

for(int i = 0 ; i < 4*N ; i++) t[i] = 0;

int n;
cin >> n;
assert(2 <= n and n <= 100000);
ll val[N];
for (int i = 1; i <= n; i++) {
cin >> val[i];
assert(1 <= val[i] and val[i] <= 1000000);
}
ll u, v;
for (int i = 0; i < n - 1; i++) {
cin >> u >> v;
assert(1 <= u and u <= n);
assert(1 <= v and v <= n);
adj[u].pb(v);
adj[v].pb(u);
}
dfs(1, 0);
vector<PLL> vec;
vector<int> pos(n + 1, 0);
for (int i = 1; i <= n; i++) {
vec.pb({dis[i], i});
}
sort(all(vec));
int m = n;
for (int i = 1; i <= m; i++) {
pos[vec[i - 1].S] = i;
a[i] = val[vec[i - 1].S];
}
build(1, 1, m);
int q;
cin >> q;
assert(2 <= q and q <= 100000);
while (q--) {
int type;
cin >> type;
if (type == 1) {
ll x, y;
cin >> x >> y;
assert(1 <= x and x <= n);
assert(1 <= y and y <= 1000000);
update(1, 1, m, pos[x], y);
val[x] += y;
a[pos[x]] += y;
} else {
ll x;
cin >> x;
assert(1 <= x and x <= 1000000000000);
int ind = get_first(1, 1, m, 1, m, x);
if (ind == -1) {
cout << ind << endl;
} else {
v = a[ind];
cout << dis[vec[ind - 1].S] << endl;
}
}
}
}

return 0;
}

Second solution

from collections import defaultdict

MAXN = int(1e12) + 10


class Fenwick:
def __init__(self):
self.f = defaultdict(lambda: MAXN)

def upd(self, p, x):
p = MAXN - p - 1
while p < MAXN:
self.f[p] = min(self.f[p], x)
p += p & -p

def get(self, p):
p = MAXN - p - 1
ans = MAXN
while p > 0:
ans = min(ans, self.f[p])
p ^= p & -p
return ans


t = int(input())
while t > 0:
t -= 1
n = int(input())
a = list(map(int, input().split()))
g = [[] for i in range(n)]
h = [0] * n
for i in range(n - 1):
v, u = map(int, input().split())
v -= 1
u -= 1
g[v] += [u]
g[u] += [v]
fen = Fenwick()


def dfs(v, p):
fen.upd(a[v], h[v])
for u in g[v]:
if p != u:
h[u] = h[v] + 1
dfs(u, v)


dfs(0, -1)
q = int(input())
while q > 0:
q -= 1
query = list(map(int, input().split()))
if query[0] == 1:
query[1] -= 1
a[query[1]] += query[2]
fen.upd(a[query[1]], h[query[1]])
else:
ans = fen.get(query[1] + 1)
print(-1 if ans == MAXN else ans)