EntropyIncreaser

Tree Division

Dec 16th, 2017
190
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.88 KB | None | 0 0
  1. #include <cstdio>
  2.  
  3. #include <algorithm>
  4.  
  5. using namespace std;
  6.  
  7. struct node {
  8.     int l, r;
  9.     int d, lazy;
  10.     node* ch[2];
  11.  
  12.     void push_down();
  13.     int query(int l, int r);
  14.     void change(int l, int r, int x);
  15. } *root;
  16.  
  17. struct edge {
  18.     int v;
  19.     edge* next;
  20. };
  21.  
  22. const int N = 100010;
  23.  
  24. int P;
  25. int d[N], sub[N], heav[N], dep[N], top[N], f[N], id[N], revid[N];
  26. bool vis[N];
  27. edge* g[N];
  28.  
  29. void dfs(int u);
  30. void dfs2(int u);
  31. void construct_tree(node*& p, int l, int r);
  32. void add_edge(int u, int v);
  33. int safe_add(int x, int y);
  34. int safe_multiply(int x, int y);
  35. void change(int x, int y, int z);
  36. int query(int x, int y);
  37.  
  38. int main() {
  39.     int n, m, r, u, v, o, x, y, z;
  40.     scanf("%d%d%d%d", &n, &m, &r, &P);
  41.     for (int i = 1; i <= n; ++i) {
  42.         scanf("%d", &d[i]);
  43.         d[i] %= P;
  44.         if (d[i] < 0)
  45.             d[i] += P;
  46.     }
  47.     for (int i = 1; i < n; ++i) {
  48.         scanf("%d%d", &u, &v);
  49.         add_edge(u, v);
  50.         add_edge(v, u);
  51.     }
  52.     dfs(r);
  53.     dfs2(r);
  54.     construct_tree(root, 1, n);
  55.     while (m--) {
  56.         scanf("%d", &o);
  57.         switch (o) {
  58.         case 1:
  59.             scanf("%d%d%d", &x, &y, &z);
  60.             z %= P;
  61.             if (z < 0)
  62.                 x += P;
  63.             change(x, y, z);
  64.             break;
  65.         case 2:
  66.             scanf("%d%d", &x, &y);
  67.             printf("%d\n", query(x, y));
  68.             break;
  69.         case 3:
  70.             scanf("%d%d", &x, &z);
  71.             root->change(id[x], id[x] + sub[x] - 1, z);
  72.             break;
  73.         case 4:
  74.             scanf("%d", &x);
  75.             printf("%d\n", root->query(id[x], id[x] + sub[x] - 1));
  76.             break;
  77.         default: break;
  78.         }
  79.     }
  80.     return 0;
  81. }
  82.  
  83. inline void add_edge(int u, int v) {
  84.     static edge pool[N << 1];
  85.     static int cnt;
  86.     edge* p = pool + cnt++;
  87.     p->v = v;
  88.     p->next = g[u];
  89.     g[u] = p;
  90. }
  91.  
  92. void construct_tree(node*& p, int l, int r) {
  93.     static node pool[N << 1];
  94.     static int cnt;
  95.     p = pool + cnt++;
  96.     p->l = l;
  97.     p->r = r;
  98.     if (l == r) {
  99.         p->d = d[revid[l]];
  100.         return;
  101.     }
  102.     construct_tree(p->ch[0], l, (l + r) >> 1);
  103.     construct_tree(p->ch[1], ((l + r) >> 1) + 1, r);
  104.     p->d = safe_add(p->ch[0]->d, p->ch[1]->d);
  105. }
  106.  
  107. void dfs(int u) {
  108.     vis[u] = true;
  109.     sub[u] = 1;
  110.     for (edge* p = g[u]; p; p = p->next) {
  111.         if (vis[p->v])
  112.             continue;
  113.         f[p->v] = u;
  114.         dep[p->v] = dep[u] + 1;
  115.         dfs(p->v);
  116.         sub[u] += sub[p->v];
  117.         if (sub[heav[u]] < sub[p->v])
  118.             heav[u] = p->v;
  119.     }
  120. }
  121.  
  122. void dfs2(int u) {
  123.     static int cnt;
  124.     id[u] = ++cnt;
  125.     revid[cnt] = u;
  126.     if (heav[u]) {
  127.         top[heav[u]] = top[u];
  128.         dfs2(heav[u]);
  129.     }
  130.     for (edge* p = g[u]; p; p = p->next) {
  131.         if (u != f[p->v] || p->v == heav[u])
  132.             continue;
  133.         top[p->v] = p->v;
  134.         dfs2(p->v);
  135.     }
  136. }
  137.  
  138. inline int safe_add(int x, int y) {
  139.     x += y;
  140.     if (x >= P)
  141.         return x - P;
  142.     return x;
  143. }
  144.  
  145. inline int safe_multiply(int x, int y)
  146. { return (long long)x * y % P; }
  147.  
  148. inline void node::push_down() {
  149.     if (!lazy)
  150.         return;
  151.     ch[0]->lazy = safe_add(ch[0]->lazy, lazy);
  152.     ch[1]->lazy = safe_add(ch[1]->lazy, lazy);
  153.     d = safe_add(d, safe_multiply(lazy, r - l + 1));
  154.     lazy = 0;
  155. }
  156.  
  157. int node::query(int l, int r) {
  158.     if (this->l == l && this->r == r)
  159.         return safe_add(d, safe_multiply(lazy, r - l + 1));
  160.     push_down();
  161.     if (ch[0]->r >= r)
  162.         return ch[0]->query(l, r);
  163.     if (ch[1]->l <= l)
  164.         return ch[1]->query(l, r);
  165.     return safe_add(ch[0]->query(l, ch[0]->r),
  166.                     ch[1]->query(ch[1]->l, r));
  167. }
  168.  
  169. void node::change(int l, int r, int x) {
  170.     if (this->l == l && this->r == r) {
  171.         lazy = safe_add(lazy, x);
  172.         return;
  173.     }
  174.     push_down();
  175.     d = safe_add(d, safe_multiply(x, r - l + 1));
  176.     if (ch[0]->r >= r) {
  177.         ch[0]->change(l, r, x);
  178.         return;
  179.     }
  180.     if (ch[1]->l <= l) {
  181.         ch[1]->change(l, r, x);
  182.         return;
  183.     }
  184.     ch[0]->change(l, ch[0]->r, x);
  185.     ch[1]->change(ch[1]->l, r, x);
  186. }
  187.  
  188. inline void change(int x, int y, int z) {
  189.     int a = top[x], b = top[y];
  190.     while (a != b) {
  191.         if (dep[a] < dep[b]) {
  192.             swap(a, b);
  193.             swap(x, y);
  194.         }
  195.         root->change(id[a], id[x], z);
  196.         x = f[a];
  197.         a = top[x];
  198.     }
  199.     if (dep[x] > dep[y])
  200.         swap(x, y);
  201.     root->change(id[x], id[y], z);
  202. }
  203.  
  204. inline int query(int x, int y) {
  205.     int a = top[x], b = top[y], ret = 0;
  206.     while (a != b) {
  207.         if (dep[a] < dep[b]) {
  208.             swap(a, b);
  209.             swap(x, y);
  210.         }
  211.         ret = safe_add(ret, root->query(id[a], id[x]));
  212.         x = f[a];
  213.         a = top[x];
  214.     }
  215.     if (dep[x] > dep[y])
  216.         swap(x, y);
  217.     return safe_add(ret, root->query(id[x], id[y]));
  218. }
Advertisement
Add Comment
Please, Sign In to add comment