/tmp/solutions/build/dynamic_tree_subtree_add_subtree_sum-main.cpp:
    1|       |#include <common.h>
    2|       |prelude;
    3|       |
    4|       |namespace {
    5|       |
    6|       |constexpr int N = 200001;
    7|       |
    8|       |struct Node {
    9|       |  i64 sum;
   10|       |  i64 sum_;
   11|       |  i64 add;
   12|       |  int size;
   13|       |  int size_;
   14|       |  int p;
   15|       |  int ch[2];
   16|       |  i8 rev;
   17|       |  i8 k;
   18|       |} node[N];
   19|       |
   20|  2.15M|def reverse(int x) -> void { node[x].rev ^= 1; }
   21|       |
   22|  3.87M|def pushdown(int x) -> void {
   23|  3.87M|  if (node[x].rev) {
  ------------------
  |  Branch (23:7): [True: 26.08%, False: 73.92%]
  ------------------
   24|  1.01M|    std::swap(node[x].ch[0], node[x].ch[1]);
   25|  1.01M|    node[node[x].ch[0]].k = 0;
   26|  1.01M|    node[node[x].ch[1]].k = 1;
   27|  1.01M|    reverse(node[x].ch[0]);
   28|  1.01M|    reverse(node[x].ch[1]);
   29|  1.01M|    node[x].rev = 0;
   30|  1.01M|  }
   31|  3.87M|}
   32|       |
   33|  3.57M|def maintain(int x) -> void {
   34|  3.57M|  node[x].size =
   35|  3.57M|      node[node[x].ch[0]].size + 1 + node[node[x].ch[1]].size + node[x].size_;
   36|  3.57M|  node[x].sum = node[node[x].ch[0]].sum + node[node[x].ch[1]].sum +
   37|  3.57M|                node[x].sum_ + node[x].size * node[x].add;
   38|  3.57M|}
   39|       |
   40|  2.54M|def rotateup(int x) -> void {
   41|  2.54M|  int p = node[x].p;
   42|  2.54M|  int g = node[p].p;
   43|  2.54M|  int k = node[x].k;
   44|  2.54M|  int t = node[p].k;
   45|  2.54M|  i64 b = node[x].add;
   46|  2.54M|  i64 a = node[p].add;
   47|  2.54M|  node[x].add = a + b;
   48|  2.54M|  node[p].add = -b;
   49|  2.54M|  node[node[x].ch[k ^ 1]].add += b;
   50|  2.54M|  node[node[x].ch[k ^ 1]].sum += b * node[node[x].ch[k ^ 1]].size;
   51|  2.54M|  node[node[x].ch[k ^ 1]].p = p;
   52|  2.54M|  node[node[x].ch[k ^ 1]].k = k;
   53|  2.54M|  node[p].ch[k] = node[x].ch[k ^ 1];
   54|  2.54M|  node[p].p = x;
   55|  2.54M|  node[p].k = k ^ 1;
   56|  2.54M|  node[x].ch[k ^ 1] = p;
   57|  2.54M|  node[x].p = g;
   58|  2.54M|  node[x].k = t;
   59|  2.54M|  if (t != -1) {
  ------------------
  |  Branch (59:7): [True: 41.90%, False: 58.10%]
  ------------------
   60|  1.06M|    node[g].ch[t] = x;
   61|  1.06M|  }
   62|  2.54M|  maintain(p);
   63|  2.54M|}
   64|       |
   65|  3.17M|def is_root(int x) -> bool { return node[x].k == -1; }
   66|       |
   67|  1.03M|def splay(int x) -> void {
   68|  1.03M|  pushdown(x);
   69|  2.10M|  while (!is_root(x)) {
  ------------------
  |  Branch (69:10): [True: 51.01%, False: 48.99%]
  ------------------
   70|  1.07M|    if (int p = node[x].p; is_root(p)) {
  ------------------
  |  Branch (70:28): [True: 34.55%, False: 65.45%]
  ------------------
   71|   370k|      pushdown(p);
   72|   370k|      pushdown(x);
   73|   370k|      rotateup(x);
   74|   702k|    } else {
   75|   702k|      int g = node[p].p;
   76|   702k|      pushdown(g);
   77|   702k|      pushdown(p);
   78|   702k|      pushdown(x);
   79|   702k|      if (node[x].k == node[p].k) {
  ------------------
  |  Branch (79:11): [True: 54.18%, False: 45.82%]
  ------------------
   80|   380k|        rotateup(p);
   81|   380k|        rotateup(x);
   82|   380k|      } else {
   83|   321k|        rotateup(x);
   84|   321k|        rotateup(x);
   85|   321k|      }
   86|   702k|    }
   87|  1.07M|  }
   88|  1.03M|}
   89|       |
   90|   264k|def access(int x) -> void {
   91|   264k|  splay(x);
   92|   264k|  node[node[x].ch[1]].k = -1;
   93|   264k|  node[x].sum_ += node[node[x].ch[1]].sum;
   94|   264k|  node[x].size_ += node[node[x].ch[1]].size;
   95|   264k|  node[x].ch[1] = 0;
   96|   264k|  maintain(x);
   97|  1.03M|  while (int p = node[x].p) {
  ------------------
  |  Branch (97:14): [True: 74.35%, False: 25.65%]
  ------------------
   98|   765k|    splay(p);
   99|   765k|    node[node[p].ch[1]].k = -1;
  100|   765k|    node[p].sum_ += node[node[p].ch[1]].sum;
  101|   765k|    node[p].size_ += node[node[p].ch[1]].size;
  102|   765k|    node[p].sum_ -= node[x].sum;
  103|   765k|    node[p].size_ -= node[x].size;
  104|   765k|    node[p].ch[1] = x;
  105|   765k|    node[x].k = 1;
  106|   765k|    rotateup(x);
  107|   765k|    maintain(x);
  108|   765k|  }
  109|   264k|}
  110|       |
  111|       |int head[N];
  112|       |struct {
  113|       |  int to;
  114|       |  int next;
  115|       |} edge[N * 2];
  116|       |
  117|  14.8k|def build(int u, int p) -> void {
  118|  44.6k|  for (int e = head[u]; e; e = edge[e].next) {
                                         ^29.7k
  ------------------
  |  Branch (118:25): [True: 66.67%, False: 33.33%]
  ------------------
  119|  29.7k|    int v = edge[e].to;
  120|  29.7k|    if (v != p) {
  ------------------
  |  Branch (120:9): [True: 50.00%, False: 50.00%]
  ------------------
  121|  14.8k|      build(v, u);
  122|  14.8k|      node[v + 1].p = u + 1;
  123|  14.8k|      node[u + 1].sum_ += node[v + 1].sum;
  124|  14.8k|      node[u + 1].size_ += node[v + 1].size;
  125|  14.8k|    }
  126|  29.7k|  }
  127|  14.8k|  node[u + 1].sum = node[u + 1].sum_;
  128|  14.8k|  node[u + 1].size = node[u + 1].size_ + 1;
  129|  14.8k|}
  130|       |
  131|       |} // namespace
  132|       |
  133|      1|int main() {
  134|      1|  rd rd;
  135|      1|  wt wt;
  136|      1|  int n = rd.uh();
  137|      1|  int q = rd.uh();
  138|      1|#ifdef LOCAL
  139|      1|  std::memset(head, 0, 4 * n);
  140|      1|#endif
  141|  14.8k|  for (int i = 1; i <= n; ++i) node[i] = {.sum_ = rd.uw(), .k = -1};
                                        ^14.8k^14.8k
  ------------------
  |  Branch (141:19): [True: 99.99%, False: 0.01%]
  ------------------
  142|  14.8k|  for (int i = 1; i != n; ++i) {
                                        ^14.8k
  ------------------
  |  Branch (142:19): [True: 99.99%, False: 0.01%]
  ------------------
  143|  14.8k|    int u = rd.uh();
  144|  14.8k|    int v = rd.uh();
  145|  14.8k|    edge[i * 2 | 0] = {v, head[u]}, head[u] = i * 2 | 0;
  146|  14.8k|    edge[i * 2 | 1] = {u, head[v]}, head[v] = i * 2 | 1;
  147|  14.8k|  }
  148|      1|  build(0, 0);
  149|  99.1k|  while (q--) {
  ------------------
  |  Branch (149:10): [True: 100.00%, False: 0.00%]
  ------------------
  150|  99.1k|    let t = rd.u1();
  151|  99.1k|    if (t == 0) {
  ------------------
  |  Branch (151:9): [True: 33.28%, False: 66.72%]
  ------------------
  152|  32.9k|      int u = rd.uh() + 1;
  153|  32.9k|      int v = rd.uh() + 1;
  154|  32.9k|      access(u);
  155|  32.9k|      reverse(u);
  156|  32.9k|      access(v);
  157|  32.9k|      node[node[v].ch[0]].p = 0;
  158|  32.9k|      node[node[v].ch[0]].k = -1;
  159|  32.9k|      node[node[v].ch[0]].add += node[v].add;
  160|  32.9k|      node[v].ch[0] = 0;
  161|  32.9k|      int w = rd.uh() + 1;
  162|  32.9k|      int x = rd.uh() + 1;
  163|  32.9k|      access(w);
  164|  32.9k|      reverse(w);
  165|  32.9k|      access(x);
  166|  32.9k|      node[w].p = x;
  167|  32.9k|      node[w].add -= node[x].add;
  168|  32.9k|      node[w].sum -= node[x].add * node[w].size;
  169|  32.9k|      node[x].sum_ += node[w].sum;
  170|  32.9k|      node[x].size_ += node[w].size;
  171|  32.9k|    }
  172|  99.1k|    if (t == 1) {
  ------------------
  |  Branch (172:9): [True: 33.26%, False: 66.74%]
  ------------------
  173|  32.9k|      int u = rd.uh() + 1;
  174|  32.9k|      int p = rd.uh() + 1;
  175|  32.9k|      i64 x = rd.uw();
  176|  32.9k|      access(u);
  177|  32.9k|      reverse(u);
  178|  32.9k|      access(p);
  179|  32.9k|      node[u].add += x;
  180|  32.9k|      node[u].sum += x * node[u].size;
  181|  32.9k|    }
  182|  99.1k|    if (t == 2) {
  ------------------
  |  Branch (182:9): [True: 33.46%, False: 66.54%]
  ------------------
  183|  33.1k|      int u = rd.uh() + 1;
  184|  33.1k|      int p = rd.uh() + 1;
  185|  33.1k|      access(u);
  186|  33.1k|      reverse(u);
  187|  33.1k|      access(p);
  188|  33.1k|      i64 ans = node[u].sum + node[u].size * node[p].add;
  189|  33.1k|      wt.ud(ans);
  190|  33.1k|    }
  191|  99.1k|  }
  192|      1|  return 0;
  193|      1|}