Description

物理学家小C的研究正遇到某个瓶颈。

他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球。主星球没有依赖星球。

我们定义依赖关系如下:若星球a的依赖星球是b,则有星球a依赖星球b.此外,依赖关系具有传递性,即若星球a依赖星球b,星球b依赖星球c,则有星球a依赖星球c.

对于这个神秘的星系中,小C初步探究了它的性质,发现星球之间的依赖关系是无环的。并且从星球a出发只能直接到达它的依赖星球b.

每个星球i都有一个能量系数wi.小C想进行若干次实验,第i次实验,他将从飞船上向星球di发射一个初始能量为0的能量收集器,能量收集器会从星球di开始前往主星球,并收集沿途每个星球的部分能量,收集能量的多少等于这个星球的能量系数。

但是星系的构成并不是一成不变的,某些时刻,星系可能由于某些复杂的原因发生变化。

有些时刻,某个星球能量激发,将使得所有依赖于它的星球以及他自己的能量系数均增加一个定值。还有可能在某些时刻,某个星球的依赖星球会发生变化,但变化后依然满足依赖关系是无环的。

现在小C已经测定了时刻0时每个星球的能量系数,以及每个星球(除了主星球之外)的依赖星球。接下来的m个时刻,每个时刻都会发生一些事件。其中小C可能会进行若干次实验,对于他的每一次实验,请你告诉他这一次实验能量收集器的最终能量是多少。

Input

第一行一个整数n,表示星系的星球数。

接下来n-1行每行一个整数,分别表示星球2-n的依赖星球编号。

接下来一行n个整数,表示每个星球在时刻0时的初始能量系数wi.

接下来一行一个整数m,表示事件的总数。

事件分为以下三种类型。

(1)"Q di"表示小C要开始一次实验,收集器的初始位置在星球di.

(2)"C xi yi"表示星球xi的依赖星球变为了星球yi.

(3)"F pi qi"表示星球pi能量激发,常数为qi.

Output

对于每一个事件类型为Q的事件,输出一行一个整数,表示此次实验的收集器最终能量。

这个应该是伪 $ETT$,不知道真正的 $ETT$ 该咋写.

开始卡了半天常数,本地 $25s$,交上去却一顿 T,后来改用结构体存变量就跑的飞快.

以后写数据结构就都用结构体存了

  1. #include <cstdio>
  2. #include <algorithm> E
  3. #define N 200005
  4. #define ll long long
  5. #define lson t[x].ch[0]
  6. #define rson t[x].ch[1]
  7. #define setIO(s) freopen(s".in", "r", stdin)
  8. using namespace std;
  9. int edges, tim, root = 0, top;
  10. int sta[N], hd[N], to[N], nex[N], L[N], R[N], euler[N], val[N];
  11. inline void addedge(int u, int v)
  12. {
  13. nex[++edges] = hd[u], hd[u] = edges, to[edges] = v;
  14. }
  15. struct Stack
  16. {
  17. int x, i;
  18. Stack(int x = 0, int i = 0) : x(x), i(i) {}
  19. }A[N];
  20. struct Node
  21. {
  22. int siz, d, ch[2], f;
  23. ll sum, val, lazy;
  24. }t[N];
  25. inline int get(int x)
  26. {
  27. return t[t[x].f].ch[1] == x;
  28. }
  29. inline void pushup(int x)
  30. {
  31. t[x].siz = t[lson].siz + t[rson].siz + t[x].d;
  32. t[x].sum = t[lson].sum + t[rson].sum + t[x].val;
  33. }
  34. inline void mark(int x, ll v)
  35. {
  36. t[x].val += 1ll * t[x].d * v;
  37. t[x].sum += 1ll * t[x].siz * v;
  38. t[x].lazy += v;
  39. }
  40. inline void pushdown(int x)
  41. {
  42. if(t[x].lazy)
  43. {
  44. if(lson) mark(lson, t[x].lazy);
  45. if(rson) mark(rson, t[x].lazy);
  46. t[x].lazy = 0;
  47. }
  48. }
  49. inline void rotate(int x)
  50. {
  51. int old = t[x].f, fold = t[old].f, which = get(x);
  52. t[old].ch[which] = t[x].ch[which ^ 1], t[t[old].ch[which]].f = old;
  53. t[x].ch[which ^ 1] = old, t[old].f = x, t[x].f = fold;
  54. if(fold) t[fold].ch[t[fold].ch[1] == old] = x;
  55. pushup(old), pushup(x);
  56. }
  57. inline void splay(int x, int &tar)
  58. {
  59. int u = t[tar].f, v = 0;
  60. for(int g = x ; g ; sta[++v] = g, g = t[g].f);
  61. for(int i = v ; i >= 1; --i) pushdown(sta[i]);
  62. for(int fa; (fa = t[x].f) ^ u; rotate(x))
  63. if(t[fa].f ^ u)
  64. rotate(get(fa) == get(x) ? fa: x);
  65. tar = x;
  66. }
  67. void solve()
  68. {
  69. top = 0;
  70. A[++ top] = Stack(1, hd[1]), L[1] = ++tim, t[tim].d = 1, t[tim].val = (ll) val[1];
  71. for( ; top ; )
  72. {
  73. Stack u = A[top];
  74. if(u.i)
  75. {
  76. A[top].i = nex[A[top].i];
  77. A[++ top] = Stack(to[u.i], hd[to[u.i]]);
  78. L[to[u.i]] = ++tim;
  79. t[tim].d = 1, t[tim].val = (ll) val[to[u.i]];
  80. }
  81. else
  82. {
  83. R[u.x] = ++tim;
  84. t[tim].d = -1, t[tim].val = (ll) -val[u.x];
  85. -- top;
  86. }
  87. }
  88. }
  89. int build(int l, int r, int ff)
  90. {
  91. int mid = (l + r) >> 1;
  92. t[mid].f = ff;
  93. if(mid > l) t[mid].ch[0] = build(l, mid - 1, mid);
  94. if(r > mid) t[mid].ch[1] = build(mid + 1, r, mid);
  95. if(mid == 1) t[mid].ch[0] = tim + 1, t[tim + 1].f = mid;
  96. if(mid == tim) t[mid].ch[1] = tim + 2, t[tim + 2].f = mid;
  97. pushup(mid);
  98. return mid;
  99. }
  100. int pre(int x)
  101. {
  102. int g = root;
  103. splay(x, root);
  104. for(x = lson; rson ; pushdown(x), x = rson);
  105. splay(g, root);
  106. return x;
  107. }
  108. int nxt(int x)
  109. {
  110. int g = root;
  111. splay(x, root);
  112. for(x = rson; lson ; pushdown(x), x = lson);
  113. splay(g, root);
  114. return x;
  115. }
  116. int main()
  117. {
  118. // setIO("input");
  119. int n, m, i, j, x, y;
  120. scanf("%d", &n);
  121. for(i = 2; i <= n ; ++i) scanf("%d", &x), addedge(x, i);
  122. for(i = 1; i <= n ; ++i) scanf("%d", &val[i]);
  123. solve(), root = build(1, tim , 0);
  124. scanf("%d", &m);
  125. for(int cas = 1; cas <= m; ++cas)
  126. {
  127. char str[4];
  128. scanf("%s", str);
  129. if(str[0] == 'Q')
  130. {
  131. scanf("%d", &x), splay(L[x], root), printf("%lld\n", t[root].sum - t[t[root].ch[1]].sum);
  132. }
  133. if(str[0] == 'C')
  134. {
  135. scanf("%d%d", &x, &y);
  136. int l = pre(L[x]), r = nxt(R[x]), key, k;
  137. splay(l, root), splay(r, t[root].ch[1]), key = t[t[root].ch[1]].ch[0];
  138. t[key].f = t[t[root].ch[1]].ch[0] = 0, pushup(t[root].ch[1]), pushup(root);
  139. splay(L[y], root), splay(nxt(L[y]), t[root].ch[1]);
  140. t[t[root].ch[1]].ch[0] = key, t[key].f = t[root].ch[1], pushup(t[root].ch[1]), pushup(root);
  141. }
  142. if(str[0] == 'F')
  143. {
  144. scanf("%d%d", &x, &y);
  145. splay(pre(L[x]), root), splay(nxt(R[x]), t[root].ch[1]);
  146. int key = t[t[root].ch[1]].ch[0];
  147. mark(key, 1ll * y);
  148. }
  149. }
  150. return 0;
  151. }

  

递归:

  1. #include <cstdio>
  2. #include <algorithm>
  3. #define N 200005
  4. #define ll long long
  5. #define lson t[x].ch[0]
  6. #define rson t[x].ch[1]
  7. #define setIO(s) freopen(s".in", "r", stdin)
  8. using namespace std;
  9. int edges, tim, root = 0;
  10. int sta[N], hd[N], to[N], nex[N], L[N], R[N], euler[N], val[N];
  11. inline void addedge(int u, int v)
  12. {
  13. nex[++edges] = hd[u], hd[u] = edges, to[edges] = v;
  14. }
  15. struct Node
  16. {
  17. int siz, d, ch[2], f;
  18. ll sum, val, lazy;
  19. }t[N];
  20. inline int get(int x)
  21. {
  22. return t[t[x].f].ch[1] == x;
  23. }
  24. inline void pushup(int x)
  25. {
  26. t[x].siz = t[lson].siz + t[rson].siz + t[x].d;
  27. t[x].sum = t[lson].sum + t[rson].sum + t[x].val;
  28. }
  29. inline void mark(int x, ll v)
  30. {
  31. t[x].val += 1ll * t[x].d * v;
  32. t[x].sum += 1ll * t[x].siz * v;
  33. t[x].lazy += v;
  34. }
  35. inline void pushdown(int x)
  36. {
  37. if(t[x].lazy)
  38. {
  39. if(lson) mark(lson, t[x].lazy);
  40. if(rson) mark(rson, t[x].lazy);
  41. t[x].lazy = 0;
  42. }
  43. }
  44. inline void rotate(int x)
  45. {
  46. int old = t[x].f, fold = t[old].f, which = get(x);
  47. t[old].ch[which] = t[x].ch[which ^ 1], t[t[old].ch[which]].f = old;
  48. t[x].ch[which ^ 1] = old, t[old].f = x, t[x].f = fold;
  49. if(fold) t[fold].ch[t[fold].ch[1] == old] = x;
  50. pushup(old), pushup(x);
  51. }
  52. inline void splay(int x, int &tar)
  53. {
  54. int u = t[tar].f, v = 0;
  55. for(int g = x ; g ; sta[++v] = g, g = t[g].f);
  56. for(int i = v ; i >= 1; --i) pushdown(sta[i]);
  57. for(int fa; (fa = t[x].f) ^ u; rotate(x))
  58. if(t[fa].f ^ u)
  59. rotate(get(fa) == get(x) ? fa: x);
  60. tar = x;
  61. }
  62. void dfs(int u)
  63. {
  64. L[u] = ++tim;
  65. t[tim].d = 1, t[tim].val = (ll)val[u];
  66. for(int i = hd[u] ; i ; i = nex[i]) dfs(to[i]);
  67. R[u] = ++tim;
  68. t[tim].d = -1, t[tim].val = (ll)-val[u];
  69. }
  70. int build(int l, int r, int ff)
  71. {
  72. int mid = (l + r) >> 1;
  73. t[mid].f = ff;
  74. if(mid > l) t[mid].ch[0] = build(l, mid - 1, mid);
  75. if(r > mid) t[mid].ch[1] = build(mid + 1, r, mid);
  76. if(mid == 1) t[mid].ch[0] = tim + 1, t[tim + 1].f = mid;
  77. if(mid == tim) t[mid].ch[1] = tim + 2, t[tim + 2].f = mid;
  78. pushup(mid);
  79. // printf("%d %d %d\n",mid, t[mid].ch[0], t[mid].ch[1]);
  80. return mid;
  81. }
  82. int pre(int x)
  83. {
  84. int g = root;
  85. splay(x, root);
  86. for(x = lson; rson ; pushdown(x), x = rson);
  87. splay(g, root);
  88. return x;
  89. }
  90. int nxt(int x)
  91. {
  92. int g = root;
  93. splay(x, root);
  94. for(x = rson; lson ; pushdown(x), x = lson);
  95. splay(g, root);
  96. return x;
  97. }
  98. int main()
  99. {
  100. // setIO("input");
  101. int n, m, i, j, x, y;
  102. scanf("%d", &n);
  103. for(i = 2; i <= n ; ++i) scanf("%d", &x), addedge(x, i);
  104. for(i = 1; i <= n ; ++i) scanf("%d", &val[i]);
  105. dfs(1), root = build(1, tim , 0);
  106. scanf("%d", &m);
  107. for(int cas = 1; cas <= m; ++cas)
  108. {
  109. char str[4];
  110. scanf("%s", str);
  111. if(str[0] == 'Q')
  112. {
  113. scanf("%d", &x), splay(L[x], root), printf("%lld\n", t[root].sum - t[t[root].ch[1]].sum);
  114. }
  115. if(str[0] == 'C')
  116. {
  117. scanf("%d%d", &x, &y);
  118. int l = pre(L[x]), r = nxt(R[x]), key, k;
  119. splay(l, root), splay(r, t[root].ch[1]), key = t[t[root].ch[1]].ch[0];
  120. t[key].f = t[t[root].ch[1]].ch[0] = 0, pushup(t[root].ch[1]), pushup(root);
  121. splay(L[y], root), splay(nxt(L[y]), t[root].ch[1]);
  122. t[t[root].ch[1]].ch[0] = key, t[key].f = t[root].ch[1], pushup(t[root].ch[1]), pushup(root);
  123. }
  124. if(str[0] == 'F')
  125. {
  126. scanf("%d%d", &x, &y);
  127. splay(pre(L[x]), root), splay(nxt(R[x]), t[root].ch[1]);
  128. int key = t[t[root].ch[1]].ch[0];
  129. mark(key, 1ll * y);
  130. }
  131. }
  132. return 0;
  133. }

  

BZOJ 3786: 星系探索 ETT的更多相关文章

  1. BZOJ 3786: 星系探索 解题报告

    3786: 星系探索 Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅 ...

  2. bzoj 3786 星系探索 dfs+splay

    [BZOJ3786]星系探索 Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球 ...

  3. BZOJ 3786: 星系探索 [伪ETT]

    传送门 数据,标程 题意: 一颗有根树,支持询问点到根路径权值和,子树加,换父亲 欧拉序列怎么求路径权值和? 一个点的权值只会给自己的子树中的点贡献,入栈权值正出栈权值负,求前缀和就行了! 和上题一样 ...

  4. BZOJ 3786 星系探索

    Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...

  5. BZOJ 3786 星系探索 ——Splay

    子树可以移动,唔. 还是用Splay维护DFS序即可. 子树的话直接截取出来就好了. 然后求前驱后继可能麻烦一些. 添加两个虚拟节点会比较好写. #include <map> #inclu ...

  6. BZOJ 3786 星系探索 (splay+dfs序)

    题目大意:给你一棵树,支持一下三种操作 1.获取某节点到根节点的路径上所有节点的权值和 2.更换某棵子树的父亲 3.某子树内所有节点的权值都增加一个值w 当时想到了splay维护dfs序,查完题解发现 ...

  7. BZOJ 3786: 星系探索 欧拉游览树

    一个叫 Euler-Tour-Tree 的数据结构,说白了就是用 Splay_Tree 维护欧拉序 #include <cstring> #include <algorithm> ...

  8. 【BZOJ】3786: 星系探索

    [题意]给定一棵带点权树,三种操作: 1.询问点x到根的路径和 2.子树x内的点权加定值y 3.将点x的父亲更换为y,保证仍是树. [算法]平衡树(fhq-treap) [题解] 将树的dfs序作为序 ...

  9. [BZOJ3786]星系探索(伪ETT)

    3786: 星系探索 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1638  Solved: 506[Submit][Status][Discuss ...

随机推荐

  1. 【神经网络与深度学习】学习笔记:AlexNet&Imagenet学习笔记

    学习笔记:AlexNet&Imagenet学习笔记 ImageNet(http://www.image-net.org)是李菲菲组的图像库,和WordNet 可以结合使用 (毕业于Caltec ...

  2. Angular5 父组件获取子组件实例( ViewChildren、ViewChild用法)

    原文链接 Understanding ViewChildren, ContentChildren, and QueryList in Angular 使用场景 有时候,我们想要在父组件中访问它的子组件 ...

  3. numpy数组转置与轴变换

    numpy数组转置与轴变换 矩阵的转置 >>> import numpy as np >>> arr=np.arange(15).reshape((3,5)) &g ...

  4. queue的常见用法

    queue的使用 queue是什么? queue是一种先入先出的容器 queue的定义 引入 # include <iostream> # include <queue> us ...

  5. springboot2.0和Druid整合配置数据源

    1. idea使用spring 初始化工具初始化springboot项目(要选中web) 下一步,下一步 2. 在pom.xml中,引入Druid连接池依赖: <dependency> & ...

  6. PythonDay11

    第十一章函数使用_迭代器 今日内容 函数名的第一类对象及使用 f-strings 迭代器 函数名的第一类对象及使用 函数名可以当做值,赋值给变量 函数名可以当做容器内的元素 函数名可以当做函数的参数 ...

  7. 弹出ifream

      top.$.jBox("iframe:"+'${ctx}/synopsis/hmlwxSynopsis/addItem', {title: "添加作品",w ...

  8. Linux知识补课

    Linux补课 已经将开发环境转Linux了(当然用的是ubuntu,图像界面还是舒服一点,支持也多),不上QQ和微信的话用的还是挺舒服的,但是无奈基础欠账太多,这里赶快补一下 Linux和Unix的 ...

  9. vue-cli常用插件安装教程

    1.安装sass npm i sass-loader node-sass --save-dev 2.安装stylus cnpm install stylus --save-dev cnpm insta ...

  10. AndroidStudio Gradle手动下载和安装

    操作流程概述: 下载好的压缩包和解压后的文件夹复制到gradle-5.5.1-all --->97z1ksx6lirer3kbvdnh7jtjg文件夹下,将gradle-5.5.1-all.zi ...