Codeforces 1192B 全dfs序 + 线段树

小咪咪 2023-08-17 17:22 224阅读 0赞

题意:给你一颗树,每次会修改一条边的边权,问修改之后的树的直径是多少?

思路:来源于:https://www.cnblogs.com/TinyWong/p/11260601.html

得到树的全序dfs序之后,我们考虑用线段树维护x - 2 * y + z。维护方法和2017, 2016那道题差不多,对于每个区间维护:x, -y, z, x - 2 * y, -2 * y + z, x - 2 * y + z6个部分的最大值,然后区间合并。

代码:

  1. #include <bits/stdc++.h>
  2. #define ls (o << 1)
  3. #define rs (o << 1 | 1)
  4. #define LL long long
  5. #define INF 1e18
  6. using namespace std;
  7. const int maxn = 100010;
  8. int lp[maxn], rp[maxn], mp[maxn * 2], tot;
  9. vector<pair<int, long long> > G[maxn];
  10. LL d[maxn];
  11. void add(LL x, LL y, LL z) {
  12. G[x].push_back(make_pair(y, z));
  13. G[y].push_back(make_pair(x, z));
  14. }
  15. struct edge {
  16. int u, v;
  17. LL w;
  18. };
  19. edge a[maxn];
  20. struct Seg {
  21. LL v[6], lz;
  22. //0: a
  23. //1: b
  24. //2: c
  25. //3: a + 2 * b
  26. //4: 2 * c + b
  27. //5: a + b + 2 * c
  28. };
  29. Seg tr[maxn * 8];
  30. void pushup(int o) {
  31. //0:
  32. tr[o].v[0] = max(tr[ls].v[0], tr[rs].v[0]);
  33. //1:
  34. tr[o].v[1] = max(tr[ls].v[1], tr[rs].v[1]);
  35. //2:
  36. tr[o].v[2] = max(tr[ls].v[2], tr[rs].v[2]);
  37. //3:
  38. tr[o].v[3] = max(tr[ls].v[3], tr[rs].v[3]);
  39. tr[o].v[3] = max(tr[o].v[3], tr[ls].v[0] + 2ll * tr[rs].v[1]);
  40. //4:
  41. tr[o].v[4] = max(tr[ls].v[4], tr[rs].v[4]);
  42. tr[o].v[4] = max(tr[o].v[4], 2ll * tr[ls].v[1] + tr[rs].v[2]);
  43. //: 5
  44. tr[o].v[5] = max(tr[ls].v[5], tr[rs].v[5]);
  45. tr[o].v[5] = max(tr[o].v[5], tr[ls].v[3] + tr[rs].v[2]);
  46. tr[o].v[5] = max(tr[o].v[5], tr[ls].v[0] + tr[rs].v[4]);
  47. }
  48. void maintain(int o, LL x) {
  49. tr[o].lz += x;
  50. tr[o].v[0] += x;
  51. tr[o].v[1] -= x;
  52. tr[o].v[2] += x;
  53. tr[o].v[3] -= x;
  54. tr[o].v[4] -= x;
  55. }
  56. void pushdown(int o) {
  57. if(tr[o].lz) {
  58. maintain(ls, tr[o].lz);
  59. maintain(rs, tr[o].lz);
  60. tr[o].lz = 0;
  61. }
  62. }
  63. void build(int o, int l, int r) {
  64. tr[o].lz = 0;
  65. if(l == r) {
  66. tr[o].v[0] = tr[o].v[2] = d[mp[l]];
  67. tr[o].v[4] = tr[o].v[3] = tr[o].v[1] = -d[mp[l]];
  68. tr[o].v[5] = 0;
  69. return;
  70. }
  71. int mid = (l + r) >> 1;
  72. build(ls, l, mid);
  73. build(rs, mid + 1, r);
  74. pushup(o);
  75. }
  76. void update(int o, int l, int r, int ql, int qr, LL val) {
  77. if(l >= ql && r <= qr) {
  78. maintain(o, val);
  79. return;
  80. }
  81. int mid = (l + r) >> 1;
  82. pushdown(o);
  83. if(ql <= mid) update(ls, l, mid, ql, qr, val);
  84. if(qr > mid) update(rs, mid + 1, r, ql, qr, val);
  85. pushup(o);
  86. }
  87. void dfs(int x, int fa, LL dis) {
  88. mp[++tot] = x;
  89. lp[x] = tot;
  90. rp[x] = tot;
  91. d[x] = dis;
  92. for (auto y : G[x]) {
  93. if(y.first == fa) continue;
  94. dfs(y.first, x, dis + y.second);
  95. mp[++tot] = x;
  96. rp[x] = tot;
  97. }
  98. }
  99. int main() {
  100. int n, m;
  101. LL w, x, y, z;
  102. scanf("%d%d%lld", &n, &m, &w);
  103. for (int i = 1; i < n; i++) {
  104. scanf("%lld%lld%lld", &x, &y, &z);
  105. add(x, y, z);
  106. a[i].u = x, a[i].v = y, a[i].w = z;
  107. }
  108. dfs(1, 0, 0);
  109. build(1, 1, tot);
  110. LL ans = 0;
  111. while(m--) {
  112. scanf("%lld%lld", &x, &y);
  113. x = (x + ans) % (n - 1) + 1;
  114. y = (y + ans) % w;
  115. int p;
  116. if(lp[a[x].u] < lp[a[x].v]) p = a[x].v;
  117. else p = a[x].u;
  118. update(1, 1, tot, lp[p], rp[p], y - a[x].w);
  119. a[x].w = y;
  120. ans = tr[1].v[5];
  121. printf("%lld\n", ans);
  122. }
  123. }

  

转载于:https://www.cnblogs.com/pkgunboat/p/11551616.html

发表评论

表情:
评论列表 (有 0 条评论,224人围观)

还没有评论,来说两句吧...

相关阅读