sotanishy's code snippets for competitive programming
#define PROBLEM "https://judge.yosupo.jp/problem/vertex_add_subtree_sum"
#include <bits/stdc++.h>
#include "../../data-structure/segtree/segment_tree.hpp"
#include "../../tree/euler_tour.hpp"
using namespace std;
using ll = long long;
struct AddMonoid {
using T = ll;
static T id() { return 0; }
static T op(T a, T b) { return a + b; }
};
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int N, Q;
cin >> N >> Q;
vector<int> a(N);
for (int i = 0; i < N; ++i) cin >> a[i];
vector<vector<int>> G(N);
for (int i = 1; i < N; ++i) {
int p;
cin >> p;
G[p].push_back(i);
}
auto [in, out] = euler_tour(G, 0);
SegmentTree<AddMonoid> st(N);
for (int i = 0; i < N; ++i) st.update(in[i], a[i]);
for (int i = 0; i < Q; ++i) {
int t, u;
cin >> t >> u;
if (t == 0) {
int x;
cin >> x;
st.update(in[u], st[in[u]] + x);
} else {
cout << st.fold(in[u], out[u]) << "\n";
}
}
}
#line 1 "test/yosupo/vertex_add_subtree_sum.euler_tour.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/vertex_add_subtree_sum"
#include <bits/stdc++.h>
#line 3 "data-structure/segtree/segment_tree.hpp"
#include <bit>
#line 5 "data-structure/segtree/segment_tree.hpp"
template <typename M>
class SegmentTree {
using T = M::T;
public:
SegmentTree() = default;
explicit SegmentTree(int n) : SegmentTree(std::vector<T>(n, M::id())) {}
explicit SegmentTree(const std::vector<T>& v)
: size(std::bit_ceil(v.size())), node(2 * size, M::id()) {
std::ranges::copy(v, node.begin() + size);
for (int i = size - 1; i > 0; --i) {
node[i] = M::op(node[2 * i], node[2 * i + 1]);
}
}
T operator[](int k) const { return node[k + size]; }
void update(int k, const T& x) {
k += size;
node[k] = x;
while (k >>= 1) node[k] = M::op(node[2 * k], node[2 * k + 1]);
}
T fold(int l, int r) const {
T vl = M::id(), vr = M::id();
for (l += size, r += size; l < r; l >>= 1, r >>= 1) {
if (l & 1) vl = M::op(vl, node[l++]);
if (r & 1) vr = M::op(node[--r], vr);
}
return M::op(vl, vr);
}
template <typename F>
int find_first(int l, F cond) const {
T v = M::id();
for (l += size; l > 0; l >>= 1) {
if (l & 1) {
T nv = M::op(v, node[l]);
if (cond(nv)) {
while (l < size) {
nv = M::op(v, node[2 * l]);
if (cond(nv)) {
l = 2 * l;
} else {
v = nv, l = 2 * l + 1;
}
}
return l + 1 - size;
}
v = nv;
++l;
}
}
return -1;
}
template <typename F>
int find_last(int r, F cond) const {
T v = M::id();
for (r += size; r > 0; r >>= 1) {
if (r & 1) {
--r;
T nv = M::op(node[r], v);
if (cond(nv)) {
while (r < size) {
nv = M::op(node[2 * r + 1], v);
if (cond(nv)) {
r = 2 * r + 1;
} else {
v = nv, r = 2 * r;
}
}
return r - size;
}
v = nv;
}
}
return -1;
}
private:
int size;
std::vector<T> node;
};
#line 3 "tree/euler_tour.hpp"
/**
* @brief Euler Tour
*/
std::pair<std::vector<int>, std::vector<int>> euler_tour(
const std::vector<std::vector<int>>& G, int root) {
std::vector<int> in(G.size()), out(G.size());
int k = 0;
auto dfs = [&](auto& dfs, int v, int p) -> void {
in[v] = k++;
for (int c : G[v])
if (c != p) dfs(dfs, c, v);
out[v] = k;
};
dfs(dfs, root, -1);
return {in, out};
}
#line 7 "test/yosupo/vertex_add_subtree_sum.euler_tour.test.cpp"
using namespace std;
using ll = long long;
struct AddMonoid {
using T = ll;
static T id() { return 0; }
static T op(T a, T b) { return a + b; }
};
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int N, Q;
cin >> N >> Q;
vector<int> a(N);
for (int i = 0; i < N; ++i) cin >> a[i];
vector<vector<int>> G(N);
for (int i = 1; i < N; ++i) {
int p;
cin >> p;
G[p].push_back(i);
}
auto [in, out] = euler_tour(G, 0);
SegmentTree<AddMonoid> st(N);
for (int i = 0; i < N; ++i) st.update(in[i], a[i]);
for (int i = 0; i < Q; ++i) {
int t, u;
cin >> t >> u;
if (t == 0) {
int x;
cin >> x;
st.update(in[u], st[in[u]] + x);
} else {
cout << st.fold(in[u], out[u]) << "\n";
}
}
}