[关闭]
@Acqua 2019-03-01T11:45:39.000000Z 字数 2830 阅读 858

【模板】树链剖分(March. 1st, 2019)

算法

题目来源

代码

  1. //La Pluie
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<iostream>
  5. #define lson u << 1, l, mid
  6. #define rson u << 1 | 1, mid + 1, r
  7. #define For(i, x, y) for(int i = x; (x > y ? (i >= y) : (i <= y)); i += (x > y ? -1 : 1))
  8. using namespace std;
  9. const int N = 1e5 + 5; struct edge{ int v, next; } e[N << 1]; struct tree{ int l, r, s, lazy; } t[N << 2];
  10. int n, q, k = 1, root, mod, pos, val[N], dep[N], ftr[N], size[N], son[N], top[N], tid[N], rak[N], sum[N], head[N];
  11. void adde(int u, int v){ e[k] = (edge){v, head[u]}; head[u] = k++; }
  12. void pushdown(int u, int m){
  13. if(t[u]. lazy){
  14. t[u << 1]. s = (t[u << 1]. s + t[u]. lazy * (m - (m >> 1))) % mod;
  15. t[u << 1]. lazy = (t[u << 1]. lazy + t[u]. lazy) % mod;
  16. t[u << 1 | 1]. s = (t[u << 1 | 1]. s + t[u]. lazy * (m >> 1)) % mod;
  17. t[u << 1 | 1]. lazy = (t[u << 1 | 1]. lazy + t[u]. lazy) % mod;
  18. t[u]. lazy = 0;
  19. }
  20. }
  21. void dfs(int u, int fa){
  22. dep[u] = dep[fa] + 1; ftr[u] = fa; size[u] = 1; sum[u] = val[u];
  23. for(int i = head[u]; i != -1; i = e[i]. next){
  24. int v = e[i]. v; if(v == fa) continue;
  25. dfs(v, u); size[u] += size[v]; sum[u] = (sum[u] + sum[v]) % mod;
  26. if(son[u] == -1 || size[v] > size[son[u]]) son[u] = v;
  27. }
  28. }
  29. void getpos(int u, int rt){
  30. top[u] = rt; tid[u] = ++pos; rak[tid[u]] = u;
  31. if(son[u] == -1) return; getpos(son[u], rt);
  32. for(int i = head[u]; i != -1; i = e[i]. next){
  33. int v = e[i]. v; if(v != son[u] && v != ftr[u]) getpos(v, v); }
  34. }
  35. void pushup(int u){ t[u]. s = (t[u << 1]. s + t[u << 1 | 1]. s) % mod; }
  36. void build(int u, int l, int r){
  37. t[u]. l = l; t[u]. r = r; t[u]. s = t[u]. lazy = 0;
  38. if(l == r){t[u]. s = val[rak[l]]; return; }
  39. int mid = l + r >> 1; build(lson); build(rson); pushup(u);
  40. }
  41. void update(int u, int l, int r, int del){
  42. if(l <= t[u]. l && t[u]. r <= r){
  43. t[u]. s += del * ( t[u]. r - t[u]. l + 1);
  44. t[u]. lazy += del;
  45. return;
  46. }
  47. pushdown(u, t[u]. r - t[u]. l + 1);
  48. int mid = t[u]. l + t[u]. r >> 1;
  49. if(l <= mid) update(u << 1, l, r, del);
  50. if(r > mid) update(u << 1 | 1, l, r, del);
  51. pushup(u);
  52. }
  53. int query(int u, int l, int r){
  54. if(l <= t[u]. l && t[u]. r <= r) return t[u]. s;
  55. pushdown(u, t[u]. r - t[u]. l + 1); int res = 0;
  56. int mid = t[u]. l + t[u]. r >> 1;
  57. if(l <= mid) res += query(u << 1, l, r), res %= mod;
  58. if(r > mid) res += query(u << 1 | 1, l, r), res %= mod;
  59. return res;
  60. }
  61. void uplca(int x, int y, int z){
  62. int fx = top[x], fy = top[y];
  63. while(fx != fy){
  64. if(dep[fx] < dep[fy]) swap(x, y), swap(fx, fy);
  65. update(1, tid[fx], tid[x], z);
  66. x = ftr[fx], fx = top[x];
  67. }
  68. if(dep[x] > dep[y]) swap(x, y);
  69. update(1, tid[x], tid[y], z);
  70. }
  71. int qulca(int x, int y){
  72. int res = 0;
  73. int fx = top[x], fy = top[y];
  74. while(fx != fy){
  75. if(dep[fx] < dep[fy]) swap(x, y), swap(fx, fy);
  76. res += query(1, tid[fx], tid[x]); res %= mod;
  77. x = ftr[fx], fx = top[x];
  78. }
  79. if(dep[x] > dep[y]) swap(x, y);
  80. return (res + query(1, tid[x], tid[y])) % mod;
  81. }
  82. int main(){
  83. memset(head, -1, sizeof(head)); memset(son, -1, sizeof(son));
  84. scanf("%d %d %d %d", &n, &q, &root, &mod);
  85. For(i, 1, n) scanf("%d", &val[i]), val[i] %= mod;
  86. For(i, 1, n - 1){ int u, v; scanf("%d %d", &u, &v); adde(u, v); adde(v, u); }
  87. dfs(root, 0); getpos(root, root); build(1, 1, pos);
  88. while(q--){
  89. int ctrl, x, y, z; scanf("%d", &ctrl);
  90. if(ctrl == 1){
  91. scanf("%d %d %d", &x, &y, &z);
  92. uplca(x, y, z % mod);
  93. }
  94. else if(ctrl == 2){
  95. scanf("%d %d", &x, &y);
  96. printf("%d\n", qulca(x, y));
  97. }
  98. else if(ctrl == 3){
  99. scanf("%d %d", &x, &z);
  100. update(1, tid[x], tid[x] + size[x] - 1, z % mod);
  101. }
  102. else if(ctrl == 4){
  103. scanf("%d", &x);
  104. printf("%d\n", query(1, tid[x], tid[x] + size[x] - 1));
  105. }
  106. }
  107. return 0;
  108. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注