2016-05-09 UPD:学习了新的DFS序列分块,然后发现这个东西是战术核导弹?反正比下面的树分块不知道要快到哪里去了

  1. #include<cmath>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. using namespace std;
  6. const int N = 50003;
  7. const int M = 100003;
  8. void read(int &k) {
  9. k = 0; int fh = 1; char c = getchar();
  10. for(; c < '0' || c > '9'; c = getchar())
  11. if (c == '-') fh = -1;
  12. for(; c >= '0' && c <= '9'; c = getchar())
  13. k = (k << 1) + (k << 3) + c - '0';
  14. k = k * fh;
  15. }
  16.  
  17. struct node {int nxt, to;} E[N << 1];
  18. struct quest {int l, r, id, a, b, lca;} Q[M];
  19. int f[N][17], pos[N << 1], L[N], R[N], color[N], cal[N];
  20. int point[N], bel[N << 1], ans = 0, cnt = 0, n, m, A[M], deep[N];
  21. bool vis[N];
  22.  
  23. void ins(int x, int y) {E[++cnt].nxt = point[x]; E[cnt].to = y; point[x] = cnt;}
  24. void _(int x, int fa) {
  25. pos[L[x] = ++cnt] = x;
  26. for(int i = 1; i <= 16; ++i) {f[x][i] = f[f[x][i - 1]][i - 1]; if (f[x][i] == 0) break;}
  27. for(int tmp = point[x]; tmp; tmp = E[tmp].nxt)
  28. if (E[tmp].to != fa)
  29. {deep[E[tmp].to] = deep[x] + 1; f[E[tmp].to][0] = x; _(E[tmp].to, x);}
  30. pos[R[x] = ++cnt] = x;
  31. }
  32. int LCA(int x, int y) {
  33. if (deep[x] < deep[y]) swap(x, y);
  34. int d = deep[x] - deep[y];
  35. for(int i = 0; i <= 16; ++i) if (d & (1 << i)) x = f[x][i];
  36. if (x == y) return x;
  37. for(int i = 16; i >= 0; --i) if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
  38. return f[x][0];
  39. }
  40. bool cmp(quest A, quest B) {return bel[A.l] == bel[B.l] ? A.r < B.r : A.l < B.l;}
  41.  
  42. int check(int a, int b) {return cal[a] && cal[b] && a != b;}
  43. void update(int x) {
  44. if (vis[x]) {if (!(--cal[color[x]])) --ans;}
  45. else {if (!(cal[color[x]]++)) ++ans;}
  46. vis[x] = !vis[x];
  47. }
  48.  
  49. int main() {
  50. read(n); read(m);
  51. for(int i = 1; i <= n; ++i) read(color[i]);
  52. int lca, u, v, a, b;
  53. for(int i = 1; i <= n; ++i) {
  54. read(u); read(v);
  55. ins(u, v); ins(v, u);
  56. }
  57.  
  58. cnt = 0;
  59. _(1, 0);
  60. for(int i = 1; i <= m; ++i) {
  61. read(u); read(v); read(Q[i].a); read(Q[i].b); Q[i].id = i;
  62. lca = LCA(u, v);
  63. if (L[u] > L[v]) swap(u, v);
  64. if (u != lca) {Q[i].l = R[u]; Q[i].r = L[v]; Q[i].lca = lca;}
  65. else {Q[i].l = L[u]; Q[i].r = L[v]; Q[i].lca = 0;}
  66. }
  67.  
  68. int nn = n << 1, sq = sqrt(nn + 0.5), tmp = 0; cnt = 1;
  69. for(int i = 1; i <= nn; ++i) {
  70. bel[i] = tmp;
  71. ++cnt; if (cnt > sq) cnt = 1, ++tmp;
  72. }
  73.  
  74. sort(Q + 1, Q + m + 1, cmp);
  75.  
  76. int l = 1, r = 0, tol, tor;
  77. for(int i = 1; i <= m; ++i) {
  78. tol = Q[i].l; tor = Q[i].r;
  79. while (l < tol) update(pos[l++]);
  80. while (l > tol) update(pos[--l]);
  81. while (r < tor) update(pos[++r]);
  82. while (r > tor) update(pos[r--]);
  83. if (Q[i].lca) update(Q[i].lca);
  84. A[Q[i].id] = ans - check(Q[i].a, Q[i].b);
  85. if (Q[i].lca) update(Q[i].lca);
  86. }
  87.  
  88. for(int i = 1; i <= m; ++i)
  89. printf("%d\n", A[i]);
  90.  
  91. return 0;
  92. }

学习了树上莫队,树分块后对讯问的$dfs序$排序,然后就可以滑动树链处理答案了。

关于树链的滑动,只需要特殊处理一下$LCA$就行了。

在这里一条树链保留下来给后面的链来转移的$now$的为这条树链上所有点除去$LCA$的颜色种数。因为如果要考虑$LCA$情况就太多了,不如单独考虑$LCA$。

转移后加上当前链的$LCA$进行统计,然后再去掉这个$LCA$更新一下$now$值给后面的链转移。

这都是我的理解,说的有点不清楚,具体请看vfk的题解 OTZ 虽然不是这道题,但是通过这篇博客学习树上莫队也是很好的。

PS:压行大法使代码看起来像一堵墙

  1. #include<cmath>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #define N 50003
  6. #define M 100003
  7. #define read(x) x=getint()
  8. using namespace std;
  9. inline int getint() {int k = 0, fh = 1; char c = getchar(); for(; c < '0' || c > '9'; c = getchar()) if (c == '-') fh = -1; for(; c >= '0' && c <= '9'; c = getchar()) k = k * 10 + c - '0'; return k * fh;}
  10. int n, m, color[N], cnt = 0, fa[N][16], deep[N], dfn[N << 1], now = 0;
  11. int belong[N], cntblo = 0, sqrblo, top = 0, sta[N], ans[M], colsum[N], point[N];
  12. short v[N];
  13. struct Enode {int nxt, to;} E[N << 1];
  14. struct node {int x, y, a, b, id;} q[M];
  15. inline bool cmp(node A, node B) {return belong[A.x] == belong[B.x] ? dfn[A.y] < dfn[B.y] : dfn[A.x] < dfn[B.x];}
  16. inline void ins(int x, int y) {E[++cnt].nxt = point[x]; E[cnt].to = y; point[x] = cnt;}
  17.  
  18. inline void dfs(int x) {
  19. dfn[x] = ++cnt;
  20. int mark = top;
  21. for(int i = 1; i <= 15; ++i)
  22. fa[x][i] = fa[fa[x][i - 1]][i - 1];
  23. for(int tmp = point[x]; tmp; tmp = E[tmp].nxt) {
  24. int v = E[tmp].to;
  25. if (v == fa[x][0]) continue;
  26. deep[v] =deep[x] + 1;
  27. fa[v][0] = x;
  28. dfs(v);
  29. if (top - mark >= sqrblo) {
  30. ++cntblo;
  31. while (top != mark)
  32. belong[sta[top--]] = cntblo;
  33. }
  34. }
  35. sta[++top] = x;
  36. }
  37.  
  38. inline int LCA(int x, int y) {
  39. if (deep[x] < deep[y])
  40. swap(x, y);
  41. int k = deep[x] - deep[y];
  42. for(int j = 15; j >= 0; --j)
  43. if (k & (1 << j))
  44. x = fa[x][j];
  45. if (x == y) return x;
  46. for(int j = 15; j >= 0; --j)
  47. if (fa[x][j] != fa[y][j])
  48. x = fa[x][j], y = fa[y][j];
  49. return fa[x][0];
  50. }
  51.  
  52. inline void pushup(int x) {
  53. if (v[x]) {
  54. --colsum[color[x]];
  55. if (!colsum[color[x]])
  56. --now;
  57. } else {
  58. if (!colsum[color[x]])
  59. ++now;
  60. ++colsum[color[x]];
  61. }
  62. v[x] ^= 1;
  63. }
  64.  
  65. inline void change(int x, int y) {
  66. while (x != y) {
  67. if (deep[x] < deep[y])
  68. pushup(y), y = fa[y][0];
  69. else
  70. pushup(x), x = fa[x][0];
  71. } //O)Z这个方法好神啊!!!我为什么想不到一个一个往上跳呢QAQ
  72. }
  73.  
  74. int main() {
  75. read(n); read(m);
  76. for(int i = 1; i <= n; ++i)
  77. read(color[i]);
  78. int u, v;
  79. for(int i = 1; i <= n; ++i) {
  80. read(u); read(v);
  81. if (u == 0 || v == 0) continue;
  82. ins(u, v);
  83. ins(v, u);
  84. }
  85. sqrblo = ceil(sqrt(n));
  86. cnt = 0;
  87. dfs(1);
  88. while (top)
  89. belong[sta[top--]] = cntblo;
  90.  
  91. for(int i = 1; i <= m; ++i) {
  92. read(q[i].x); read(q[i].y); read(q[i].a); read(q[i].b); q[i].id = i;
  93. if (dfn[q[i].x] > dfn[q[i].y])
  94. swap(q[i].x, q[i].y);
  95. }
  96.  
  97. sort(q + 1, q + m + 1, cmp);
  98. q[0].x = q[0].y = 1;
  99.  
  100. for(int i = 1; i <= m; ++i) {
  101. change(q[i - 1].x, q[i].x);
  102. change(q[i - 1].y, q[i].y);
  103. int lca = LCA(q[i].x, q[i].y);
  104. pushup(lca);
  105. ans[q[i].id] = now;
  106. if (colsum[q[i].a] && colsum[q[i].b] && q[i].a != q[i].b)
  107. --ans[q[i].id];
  108. pushup(lca);
  109. }
  110.  
  111. for(int i = 1; i <= m; ++i)
  112. printf("%d\n", ans[i]);
  113. return 0;
  114. }

$SDOI2016 Round1$之前做的最后一道题了,希望省选不要爆零啊$QAQ$

【BZOJ 3735】苹果树 树上莫队(树分块+离线莫队+鬼畜的压行)的更多相关文章

  1. 【BZOJ】4129: Haruna’s Breakfast 树分块+带修改莫队算法

    [题意]给定n个节点的树,每个节点有一个数字ai,m次操作:修改一个节点的数字,或询问一条树链的数字集合的mex值.n,m<=5*10^4,0<=ai<=10^9. [算法]树分块+ ...

  2. 【BZOJ】3052: [wc2013]糖果公园 树分块+带修改莫队算法

    [题目]#58. [WC2013]糖果公园 [题意]给定n个点的树,m种糖果,每个点有糖果ci.给定n个数wi和m个数vi,第i颗糖果第j次品尝的价值是v(i)*w(j).q次询问一条链上每个点价值的 ...

  3. BZOJ3236[Ahoi2013]作业——莫队+树状数组/莫队+分块

    题目描述 输入 输出 样例输入 3 4 1 2 2 1 2 1 3 1 2 1 1 1 3 1 3 2 3 2 3 样例输出 2 2 1 1 3 2 2 1 提示 N=100000,M=1000000 ...

  4. [BZOJ 1086] [SCOI2005] 王室联邦 【树分块】

    题目链接:BZOJ - 1086 题目分析 这道题要求给树分块,使得每一块的大小在 [B, 3B] 之间,并且可以通过一个块外的节点(块根)使得整个块联通. 那么我们使用一种 DFS,维护一个栈,DF ...

  5. luogu P4887 模板 莫队二次离线 莫队 离线

    LINK:模板莫队二次离线 很早以前学的知识点 不过 很久了忘了. 考虑暴力 :每次莫队更新的时候 尝试更新一个点到一个区间的答案 可以枚举二进制下位数为k的数字 看一下区间内的这种数字有多少个. 不 ...

  6. BZOJ.3757.苹果树(树上莫队)

    题面链接 /* 代码正确性不保证..(不过交了SPOJ没WA T了最后一个点) 在DFS序做莫队 当一个点不是另一个点的LCA时,需要加上它们LCA的贡献 */ #include <cmath& ...

  7. BZOJ 1878 SDOI2009 HH的项链 树状数组/莫队算法

    题目大意:给定一个序列.求一个区间内有多少个不同的数 正解是树状数组 将全部区间依照左端点排序 然后每次仅仅统计左端点開始的每种颜色的第一个数即可了 用树状数组维护 我写的是莫队算法 莫队明显能搞 m ...

  8. BZOJ 3166 set+可持久化trie树(OR 莫队)

    思路: 1.找次大值 我们不妨设当前点是次大的 那这段区间为 左边第二个比它大的点的坐标+1 和右边第二个比它大的点的坐标-1 2.用可持久化trie树找异或最大值 也可以用莫队 //By Siriu ...

  9. 【BZOJ 3529】 [Sdoi2014]数表 (莫比乌斯+分块+离线+树状数组)

    3529: [Sdoi2014]数表 Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为能同时整除i和j的所有 ...

随机推荐

  1. 《Invert》开发日志03:一些想法

    本来标题想写“详细设计”,但是由于独立游戏开发有很强的探索性,最终项目一定是经过原型调整迭代而来的,所以在实际效果出来之前把设计做得太细并没有太大意义,现在只能先陈列目前的一些想法,不能定义“它是什么 ...

  2. QuickFIX/N 动态存储配置信息

    Acceptor或者Initiator能够为您维护尽可能多的FIX会话,因而FIX会话标识的唯一性非常重要.在QuickFIX/N中,一个FIX会话的唯一标识是由:BeginString(FIX版本号 ...

  3. url编码base编码解码十六进制

    0x25346425353425343525333525343325366125343525373725346425353125366625373825346425343425363725346225 ...

  4. javascript中String的fromCharCode()方法

    前几天遇到一个bug,后端的模板引擎在输出形如: <div title="111 aaa">内容</div> 这样的内容时,无法输出' '空格,所以只能用' ...

  5. 【转】TestFlight APP测试(IOS如何让上架前给其他人测试)

    原文网址:http://blog.csdn.net/dexin5195/article/details/43966571 大家都知道, 以前iOS项目要测试只需要上传到testflightapp.co ...

  6. AngularJS中的缓存

    欢迎大家指导与讨论 : ) 缓存篇 一个缓存就是一个组件,它可以透明地储存数据,以便以后可以更快地服务于请求.多次重复地获取资源可能会导致数据重复,消耗时间.因此缓存适用于变化性不大的一些数据,缓存能 ...

  7. QT 网络编程一

    QT如果要进行网络编程首先需要在.pro中添加如下代码:QT += network 在头文件中包含相关头文件 #include <QHostInfo> #include <QNetw ...

  8. QT 对话框一

    标准文件对话框 其函数形式如下:: QString QFileDialog::getOpenFileName ( QWidget * parent=, const QString &capti ...

  9. 读书摘要,一种新的黑客文化:programming is forgetting

    http://opentranscripts.org/transcript/programming-forgetting-new-hacker-ethic/ 这篇文章非常有意思,作者是一个计算机教师, ...

  10. opencv8-GPU之相似性计算

    Opencv支持GPU计算,并且包含成一个gpu类用来方便调用,所以不需要去加上什么__global__什么的很方便,不过同时这个类还是有不足的,待opencv小组的更新和完善. 这里先介绍在之前的& ...