[关闭]
@ZCDHJ 2018-11-05T06:57:07.000000Z 字数 2284 阅读 524

SCOI2015 情报传递

树链剖分


LOJ
这里写的是两个 log 的做法。
首先如果一个情报员是危险的,就有 当前时间-c>情报员的开始时间。也就是统计一条路径上小于某个数的数的个数,使用轻重链剖分+树状数组。注意这里的树状数组维护不再是权值,而是答案的个数。所以将每个询问按照 的大小排序,离线的搞。
常数貌似很小,Luogu 跑到第一版去了(23333

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. const int MAXN = 2e5;
  5. int n, q, tot1, tot2, edge, tim, root;
  6. int dfn[MAXN | 1], son[MAXN | 1], size[MAXN | 1], topf[MAXN | 1], depth[MAXN | 1], father[MAXN | 1], bit[MAXN | 1];
  7. struct Edge {
  8. int to;
  9. Edge *nxt;
  10. Edge(void) {}
  11. Edge(Edge *x, int y) : nxt(x), to(y) {}
  12. } e[MAXN], *firstEdge[MAXN | 1];
  13. struct Query {
  14. int x, y, c, id, ans, sum;
  15. Query(void) {}
  16. } a[MAXN | 1];
  17. struct Modify {
  18. int id, t;
  19. Modify(void) {}
  20. } b[MAXN | 1];
  21. inline int read() {
  22. register int x = 0;
  23. register char ch = getchar();
  24. while(!isdigit(ch)) ch = getchar();
  25. while(isdigit(ch)) {
  26. x = x * 10 + ch - '0';
  27. ch = getchar();
  28. }
  29. return x;
  30. }
  31. inline void addEdge(int x, int y) {
  32. e[++edge] = Edge(firstEdge[x], y);
  33. firstEdge[x] = &e[edge];
  34. }
  35. bool comp1(Query x, Query y) {
  36. return x.id - x.c < y.id - y.c;
  37. }
  38. bool comp2(Query x, Query y) {
  39. return x.id < y.id;
  40. }
  41. void dfs1(int x, int fa) {
  42. father[x] = fa;
  43. depth[x] = depth[fa] + 1;
  44. size[x] = 1;
  45. for(Edge *k = firstEdge[x]; k; k = k -> nxt) {
  46. int to = k -> to;
  47. if(to == fa) continue;
  48. dfs1(to, x);
  49. size[x] += size[to];
  50. if(size[to] > size[son[x]]) son[x] = to;
  51. }
  52. }
  53. void dfs2(int x, int ftop) {
  54. dfn[x] = ++tim;
  55. topf[x] = ftop;
  56. if(!son[x]) return;
  57. dfs2(son[x], ftop);
  58. for(Edge *k = firstEdge[x]; k; k = k -> nxt) {
  59. int to = k -> to;
  60. if(to != son[x] && to != father[x]) dfs2(to, to);
  61. }
  62. }
  63. inline void modify(int x) {
  64. while(x <= n) {
  65. ++bit[x];
  66. x += x & (-x);
  67. }
  68. }
  69. inline int query(int x) {
  70. int res = 0;
  71. while(x > 0) {
  72. res += bit[x];
  73. x -= x & (-x);
  74. }
  75. return res;
  76. }
  77. inline int queryRange(int i) {
  78. int x = a[i].x, y = a[i].y;
  79. while(topf[x] != topf[y]) {
  80. if(depth[topf[x]] < depth[topf[y]]) std::swap(x, y);
  81. a[i].ans += query(dfn[x]) - query(dfn[topf[x]] - 1);
  82. x = father[topf[x]];
  83. }
  84. if(depth[x] > depth[y]) std::swap(x, y);
  85. a[i].ans = a[i].ans + query(dfn[y]) - query(dfn[x] - 1);
  86. a[i].sum += depth[a[i].x] - depth[x] + depth[a[i].y] - depth[x] + 1;
  87. }
  88. int main() {
  89. n = read();
  90. for(int i = 1; i <= n; ++i) {
  91. int a = read();
  92. if(a == 0) root = i;
  93. else addEdge(a, i);
  94. }
  95. dfs1(root, 0);
  96. dfs2(root, root);
  97. q = read();
  98. for(int i = 1; i <= q; ++i) {
  99. int opt = read();
  100. if(opt == 1) {
  101. ++tot1;
  102. a[tot1].x = read();
  103. a[tot1].y = read();
  104. a[tot1].c = read();
  105. a[tot1].id = i;
  106. a[tot1].sum = a[tot1].ans = 0;
  107. } else {
  108. ++tot2;
  109. b[tot2].t = read();
  110. b[tot2].id = i;
  111. }
  112. }
  113. std::sort(a + 1, a + 1 + tot1, comp1);
  114. int tail = 0;
  115. for(int i = 1; i <= tot1; ++i) {
  116. while(tail < tot2 && b[tail + 1].id < a[i].id - a[i].c) {
  117. modify(dfn[b[tail + 1].t]);
  118. ++tail;
  119. }
  120. queryRange(i);
  121. }
  122. std::sort(a + 1, a + 1 + tot1, comp2);
  123. for(int i = 1; i <= tot1; ++i) printf("%d %d\n", a[i].sum, a[i].ans);
  124. return 0;
  125. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注