Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2")
- #pragma GCC optimize("Ofast")
- #pragma GCC optimize("unroll-loops")
- #include <iostream>
- #include <algorithm>
- #include <iterator>
- #include <iomanip>
- #include <cmath>
- #include <ctime>
- #include <vector>
- #include <deque>
- #include <queue>
- #include <set>
- #include <map>
- #include <stack>
- #include <string>
- #include <random>
- #include <numeric>
- #include <unordered_set>
- #include <bitset>
- #include <random>
- typedef unsigned long long ull;
- typedef long long ll;
- typedef long double lb;
- #define fast ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
- #define file_in freopen("input.txt", "r", stdin);
- #define file_in_out freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
- #define mp make_pair
- #define pii pair<int, int>
- #define all(x) (x).begin(), (x).end()
- #define fi first
- #define se second
- using namespace std;
- template<typename T>
- istream& operator>>(istream &in, vector<T> &v) {
- for (auto &it : v) {
- in >> it;
- }
- return in;
- }
- template<typename T>
- ostream& operator<<(ostream &out, vector<T> &v) {
- if (!v.empty()) {
- out << v.front();
- for (int i = 1; i < v.size(); ++i) {
- out << " " << v[i];
- }
- }
- return out;
- }
- template<typename T>
- istream& operator>>(istream &in, pair<T, T> &v) {
- in >> v.fi >> v.se;
- return in;
- }
- template<typename T1, typename T2>
- ostream& operator<<(ostream &out, pair<T1, T2> &v) {
- out << v.fi << " " << v.se;
- return out;
- }
- struct node {
- ll sum = 0, add = 0;
- };
- struct seg_tree {
- vector<ll> a;
- vector<node> t;
- seg_tree(vector<ll> b) {
- int n = b.size();
- a = b;
- t.resize(4 * n);
- build(0, 0, n);
- }
- void push(int id) {
- t[id].sum += t[id].add;
- if (id * 2 + 1 < t.size()) t[id * 2 + 1].add += t[id].add;
- if (id * 2 + 2 < t.size()) t[id * 2 + 2].add += t[id].add;
- t[id].add = 0;
- }
- void build(int id, int l, int r) {
- if (l + 1 == r) {
- t[id].sum = a[l];
- return;
- }
- int m = (l + r) / 2;
- build(id * 2 + 1, l, m);
- build(id * 2 + 2, m, r);
- t[id].sum = t[id * 2 + 1].sum + t[id * 2 + 2].sum;
- }
- ll get(int id, int l, int r, int i) {
- if (l + 1 == r) {
- push(id);
- return t[id].sum;
- }
- push(id);
- int m = (l + r) / 2;
- if (i < m) {
- return get(id * 2 + 1, l, m, i);
- } else {
- return get(id * 2 + 2, m, r, i);
- }
- }
- void update(int id, int l, int r, int lq, int rq, int x) {
- if (lq >= r || l >= rq) {
- return;
- }
- if (lq <= l && r <= rq) {
- t[id].add += x;
- push(id);
- return;
- }
- push(id);
- int m = (l + r) / 2;
- update(id * 2 + 1, l, m, lq, rq, x);
- update(id * 2 + 2, m, r, lq, rq, x);
- t[id].sum = t[id * 2 + 1].sum + t[id * 2 + 2].sum;
- }
- };
- const int LOG = 20;
- int timer = 0;
- vector<vector<int>> g;
- vector<vector<int>> up;
- vector<int> val;
- vector<ll> euler;
- vector<ll> dist;
- vector<int> tin, tout;
- void resize_all(int n) {
- val.resize(n);
- g.resize(n);
- dist.resize(n);
- tin.resize(n);
- tout.resize(n);
- up.resize(n, vector<int>(LOG));
- }
- void dfs(int v, int p = 0) {
- tin[v] = timer++;
- euler.push_back(v);
- up[v][0] = p;
- for (int i = 1; i < LOG; ++i) {
- up[v][i] = up[up[v][i - 1]][i - 1];
- }
- for (auto u : g[v]) {
- if (u != p) {
- dist[u] = dist[v] + val[u];
- dfs(u, v);
- }
- }
- euler.push_back(v);
- tout[v] = timer++;
- }
- bool isAnc(int u, int v) {
- return tin[u] <= tin[v] && tout[v] <= tout[u];
- }
- int lca(int v, int u) {
- if (isAnc(v, u)) return v;
- if (isAnc(u, v)) return u;
- for (int i = LOG - 1; i >= 0; --i) {
- if (!isAnc(up[v][i], u)) {
- v = up[v][i];
- }
- }
- return up[v][0];
- }
- int main() {
- fast
- // file_in
- // file_in_out
- int n;
- cin >> n;
- resize_all(n);
- cin >> val;
- dist[0] = val[0];
- int v, u, x;
- for (int i = 0; i < n - 1; ++i) {
- cin >> v >> u;
- --v; --u;
- g[v].push_back(u);
- g[u].push_back(v);
- }
- dfs(0);
- for (auto &it : euler) {
- it = dist[it];
- }
- seg_tree s(euler);
- int m = euler.size();
- int q;
- cin >> q;
- char type;
- while (q--) {
- cin >> type;
- if (type == '?') {
- cin >> v >> u;
- --v; --u;
- int lca_v_u = lca(v, u);
- ll sum_v = s.get(0, 0, m, tin[v]);
- ll sum_u = s.get(0, 0, m, tin[u]);
- ll sum_lca_v_u = s.get(0, 0, m, tin[lca_v_u]);
- cout << sum_v + sum_u - 2 * sum_lca_v_u + val[lca_v_u] << '\n';
- } else {
- cin >> v >> x;
- --v;
- s.update(0, 0, m, tin[v], tout[v] + 1, x - val[v]);
- val[v] = x;
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement