[关闭]
@wsndy-xx 2018-05-05T19:56:27.000000Z 字数 2869 阅读 1018

Luogu [SDOI2014]旅行

题解


题记

最近做题第一道写完代码直接过样例,然后A掉的,唉

题意

一棵树
每个节点有各自的属性(相同数字代表相同属性)和权值
4中操作
修改节点的属性
修改节点的权值
询问一条路径中所有与起点属性相同的点的价值之和
询问一条路径中所有与起点属性相同的点的最大权职


树上问题转化到链上
当然是树链剖分啦
但是属性不同怎么办
那我们就对每个属性都开一颗线段树
查询时只需找到对应属性的线段树进行查询就可以啦
对每个属性都开线段树???
空间爆炸
我们可以动态开点
(其实这题主要是练一下线段树的动态开点)
这样就可以完美的过掉这道T啦


Code

  1. #include <bits/stdc++.h>
  2. const int N = 1e5 + 10;
  3. #define gc getchar()
  4. int n, T;
  5. int bel[N], data[N], root[N];
  6. int size[N], son[N], topp[N], fa[N], deep[N], tree[N], bef[N], Tree;
  7. int tot, W[N * 20], Max[N * 20], lson[N * 20], rson[N * 20];
  8. inline int read() {
  9. int x = 0; char c = gc;
  10. while(c < '0' || c > '9') c = gc;
  11. while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
  12. return x;
  13. }
  14. struct Node {int v, nxt;} G[N << 2];
  15. int now = 1, head[N];
  16. inline void Add(int u, int v) {G[now].v = v; G[now].nxt = head[u]; head[u] = now ++;}
  17. void Dfs_1(int u, int f_, int dep) {
  18. fa[u] = f_; deep[u] = dep; size[u] = 1;
  19. for(int i = head[u]; ~ i; i = G[i].nxt) {
  20. int v = G[i].v;
  21. if(v != f_) {
  22. Dfs_1(v, u, dep + 1);
  23. size[u] += size[v];
  24. if(size[son[u]] < size[v]) son[u] = v;
  25. }
  26. }
  27. }
  28. void Dfs_2(int u, int tp) {
  29. topp[u] = tp; tree[u] = ++ Tree; bef[Tree] = u;
  30. if(!son[u]) return ;
  31. Dfs_2(son[u], tp);
  32. for(int i = head[u]; ~ i; i = G[i].nxt) {
  33. int v = G[i].v;
  34. if(v != fa[u] && v != son[u]) Dfs_2(v, v);
  35. }
  36. }
  37. void Poi_G(int l, int r, int & jd, int x, int w) {
  38. if(!jd) jd = ++ tot;
  39. W[jd] += w;
  40. if(l == r) {Max[jd] += w; return ;}
  41. int mid = (l + r) >> 1;
  42. if(x <= mid) Poi_G(l, mid, lson[jd], x, w);
  43. else Poi_G(mid + 1, r, rson[jd], x, w);
  44. Max[jd] = std:: max(Max[lson[jd]], Max[rson[jd]]);
  45. }
  46. int Ans;
  47. void Sec_A_sum(int l, int r, int jd, int x, int y) {
  48. if(! jd) return ;
  49. if(x <= l && r <= y) {Ans += W[jd]; return ;}
  50. int mid = (l + r) >> 1;
  51. if(x <= mid) Sec_A_sum(l, mid, lson[jd], x, y);
  52. if(y > mid ) Sec_A_sum(mid + 1, r, rson[jd], x, y);
  53. }
  54. void Sec_A_max(int l, int r, int jd, int x, int y) {
  55. if(! jd) return ;
  56. if(x <= l && r <= y) {Ans = std:: max(Ans, Max[jd]); return ;}
  57. int mid = (l + r) >> 1;
  58. if(x <= mid) Sec_A_max(l, mid, lson[jd], x, y);
  59. if(y > mid ) Sec_A_max(mid + 1, r, rson[jd], x, y);
  60. }
  61. inline int Sec_A_Imp(int x, int y, int Rt) {
  62. int tp1 = topp[x], tp2 = topp[y], ret(0);
  63. while(tp1 != tp2) {
  64. if(deep[tp1] < deep[tp2]) std:: swap(tp1, tp2), std:: swap(x, y);
  65. Ans = 0;
  66. Sec_A_sum(1, n, root[Rt], tree[tp1], tree[x]);
  67. ret += Ans;
  68. x = fa[tp1];
  69. tp1 = topp[x];
  70. }
  71. Ans = 0;
  72. if(deep[x] < deep[y]) std:: swap(x, y);
  73. Sec_A_sum(1, n, root[Rt], tree[y], tree[x]);
  74. ret += Ans;
  75. return ret;
  76. }
  77. inline int Sec_A_Imp2(int x, int y, int Rt) {
  78. int tp1 = topp[x], tp2 = topp[y]; Ans = 0;
  79. while(tp1 != tp2) {
  80. if(deep[tp1] < deep[tp2]) std:: swap(tp1, tp2), std:: swap(x, y);
  81. Sec_A_max(1, n, root[Rt], tree[tp1], tree[x]);
  82. x = fa[tp1];
  83. tp1 = topp[x];
  84. }
  85. if(deep[x] < deep[y]) std:: swap(x, y);
  86. Sec_A_max(1, n, root[Rt], tree[y], tree[x]);
  87. return Ans;
  88. }
  89. int main() {
  90. n = read(); T = read();
  91. for(int i = 1; i <= n; i ++) data[i] = read(), bel[i] = read();
  92. for(int i = 1; i <= n; i ++) head[i] = -1;
  93. for(int i = 1; i < n; i ++) {
  94. int a = read(), b = read();
  95. Add(a, b); Add(b, a);
  96. }
  97. Dfs_1(1, 0, 1);
  98. Dfs_2(1, 1);
  99. for(int i = 1; i <= n; i ++) Poi_G(1, n, root[bel[i]], tree[i], data[i]);
  100. while(T --) {
  101. std:: string opt; std:: cin >> opt;
  102. int x = read(), y = read();
  103. if(opt == "CC") Poi_G(1, n, root[bel[x]], tree[x], -data[x]),
  104. Poi_G(1, n, root[y], tree[x], data[x]), bel[x] = y;
  105. else if(opt == "CW") Poi_G(1, n, root[bel[x]], tree[x], y - data[x]), data[x] = y;
  106. else if(opt == "QS") std:: cout << Sec_A_Imp(x, y, bel[x]) << "\n";
  107. else std:: cout << Sec_A_Imp2(x, y, bel[x]) << "\n";
  108. }
  109. return 0;
  110. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注