题目链接  BZOJ3083

换根不能真正地换。

令当前的根为$cnt$,要查找的子树根为$x$

$1$、$x = cnt$,那么要查找的区域就是整棵树。

$2$、$x$在以$cnt$为根的子树内,那么要查找的区域就是以$x$为根的子树。

$3$、$x$在以$cnt$为根的子树外

  (1)$x$不是$cnt$的祖先,那么要查找的区域就是以$x$为根的子树。

  (2)$x$是$cnt$的祖先,设$y$为$x$到$cnt$方向上的第一个点,那么要查找的区域就是整棵树减去以$y$为根的子树。

  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. #define rep(i, a, b) for (int i(a); i <= (b); ++i)
  6. #define dec(i, a, b) for (int i(a); i >= (b); --i)
  7. #define ls i << 1
  8. #define rs i << 1 | 1
  9. #define mid ((L + R) >> 1)
  10. #define lson i << 1, L, mid
  11. #define rson i << 1 | 1, mid + 1, R
  12.  
  13. const int N = 1e5 + 10;
  14.  
  15. int f[N], fp[N], son[N], deep[N], father[N], sz[N], a[N], top[N];
  16. int n, m, tot = 0;
  17. int cnt;
  18. int s[N << 2], lazy[N << 2];
  19. vector <int> v[N];
  20.  
  21. void dfs1(int x, int fa, int dep){
  22. deep[x] = dep;
  23. father[x] = fa;
  24. son[x] = 0;
  25. sz[x] = 1;
  26. int ct = (int)v[x].size();
  27. rep(i, 0, ct - 1){
  28. int u = v[x][i];
  29. if (u == fa) continue;
  30. dfs1(u, x, dep + 1);
  31. sz[x] += sz[u];
  32. if (sz[son[x]] < sz[u]) son[x] = u;
  33. }
  34. }
  35.  
  36. void dfs2(int x, int tp){
  37. top[x] = tp;
  38. f[x] = ++tot;
  39. fp[f[x]] = x;
  40. if (son[x]) dfs2(son[x], tp);
  41. int ct = (int)v[x].size();
  42. rep(i, 0, ct - 1){
  43. int u = v[x][i];
  44. if (u == father[x] || u == son[x]) continue;
  45. dfs2(u, u);
  46. }
  47. }
  48.  
  49. inline void pushup(int i){ s[i] = min(s[ls], s[rs]); }
  50.  
  51. inline void pushdown(int i){
  52. if (lazy[i]){
  53. s[ls] = lazy[ls] = lazy[i];
  54. s[rs] = lazy[rs] = lazy[i];
  55. lazy[i] = 0;
  56. }
  57. }
  58.  
  59. void update(int i, int L, int R, int l, int r, int val){
  60. if (l <= L && R <= r){
  61. s[i] = lazy[i] = val;
  62. return;
  63. }
  64.  
  65. pushdown(i);
  66. if (l <= mid) update(lson, l, r, val);
  67. if (r > mid) update(rson, l, r, val);
  68. pushup(i);
  69. }
  70.  
  71. int query(int i, int L, int R, int l, int r){
  72. if (l <= L && R <= r) return s[i];
  73.  
  74. pushdown(i);
  75. int ret = INT_MAX;
  76. if (l <= mid) ret = min(ret, query(lson, l, r));
  77. if (r > mid) ret = min(ret, query(rson, l, r));
  78. return ret;
  79. }
  80.  
  81. void modify(int x, int y, int val){
  82. int f1 = top[x], f2 = top[y];
  83. for (; f1 ^ f2; ){
  84. if (deep[f1] < deep[f2]) swap(f1, f2), swap(x, y);
  85. update(1, 1, n, f[f1], f[x], val);
  86. x = father[f1], f1 = top[x];
  87. }
  88.  
  89. if (x == y){
  90. update(1, 1, n, f[x], f[y], val);
  91. return;
  92. }
  93.  
  94. if (deep[x] > deep[y]) swap(x, y);
  95. update(1, 1, n, f[x], f[y], val);
  96. return;
  97.  
  98. }
  99.  
  100. int twz(int x, int y){
  101. int t;
  102. for (; top[x] ^ top[y]; ) t = top[y], y = father[top[y]];
  103. return x == y ? t : son[x];
  104. }
  105.  
  106. int LCA(int x, int y){
  107. for (; top[x] ^ top[y]; ){
  108. if (deep[top[x]] < deep[top[y]]) swap(x, y);
  109. x = father[top[x]];
  110. }
  111.  
  112. return deep[x] > deep[y] ? y : x;
  113. }
  114.  
  115. int main(){
  116.  
  117. scanf("%d%d", &n, &m);
  118.  
  119. rep(i, 0, 4e5 + 10) s[i] = INT_MAX;
  120.  
  121. rep(i, 2, n){
  122. int x, y;
  123. scanf("%d%d", &x, &y);
  124. v[x].push_back(y);
  125. v[y].push_back(x);
  126. }
  127.  
  128. dfs1(1, 0, 1);
  129. dfs2(1, 1);
  130.  
  131. rep(i, 1, n){
  132. int x;
  133. scanf("%d", &x);
  134. update(1, 1, n, f[i], f[i], x);
  135. }
  136.  
  137. scanf("%d", &cnt);
  138.  
  139. while (m--){
  140. int op;
  141. scanf("%d", &op);
  142. if (op == 1) scanf("%d", &cnt);
  143. else if (op == 2){
  144. int x, y, z;
  145. scanf("%d%d%d", &x, &y, &z);
  146. modify(x, y, z);
  147. }
  148.  
  149. else{
  150. int x;
  151. scanf("%d", &x);
  152. if (x == cnt){
  153. printf("%d\n", query(1, 1, n, 1, n));
  154. continue;
  155. }
  156.  
  157. int lca = LCA(x, cnt);
  158. if (lca == x){
  159. int y = twz(x, cnt);
  160. int ret = INT_MAX;
  161. int xx = f[y], yy = f[y] + sz[y] - 1;
  162. if (xx >= 1) ret = min(ret, query(1, 1, n, 1, xx - 1));
  163. if (yy < n) ret = min(ret, query(1, 1, n, yy + 1, n));
  164. printf("%d\n", ret);
  165. continue;
  166. }
  167.  
  168. printf("%d\n", query(1, 1, n, f[x], f[x] + sz[x] - 1));
  169. }
  170. }
  171.  
  172. return 0;
  173. }

  

BZOJ 3083 遥远的国度 (换根讨论 + 树链剖分)的更多相关文章

  1. Bzoj 4196: [Noi2015]软件包管理器 树链剖分

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 721  Solved: 419[Submit][Statu ...

  2. [BZOJ 2243] [SDOI 2011] 染色 【树链剖分】

    题目链接:BZOJ - 2243 题目分析 树链剖分...写了200+行...Debug了整整一天+... 静态读代码读了 5 遍 ,没发现错误,自己做小数据也过了. 提交之后全 WA . ————— ...

  3. BZOJ 4568 [Scoi2016]幸运数字(树链剖分 + 异或线性基)

    题目链接  BZOJ 4568 考虑树链剖分+线段树维护每一段区域的异或线性基 对于每个询问,求出该点集的异或线性基.然后求一下这个线性基里面能异或出的最大值即可. #include <bits ...

  4. BZOJ 1969: [Ahoi2005]LANE 航线规划( 树链剖分 )

    首先我们要时光倒流, 倒着做, 变成加边操作维护关键边. 先随意搞出一颗树, 树上每条边都是关键边(因为是树, 去掉就不连通了)....然后加边(u, v)时, 路径(u, v)上的所有边都变成非关键 ...

  5. bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2852  Solved: 1668[Submit][Sta ...

  6. BZOJ - 3631 松鼠的新家 (树链剖分)

    题目链接 树链剖分基础题,路径权值修改+差分 #include<bits/stdc++.h> using namespace std; typedef long long ll; ; in ...

  7. BZOJ 4034 [HAOI2015]树上操作(树链剖分)

    题目链接  BZOJ4034 这道题树链剖分其实就可以了. 单点更新没问题. 相当于更新 [f[x], f[x]]这个区间. f[x]表示树链剖分之后每个点的新的标号. 区间更新的话类似DFS序,求出 ...

  8. BZOJ 3631 松鼠的新家 - 树链剖分 / 树上差分

    传送门 分析: 树链剖分:x->y,将x到y的路径加一,并将x端点的答案-1,最后统计答案. 树上差分:x->y,x+1,y+1,lca-1,fa[lca]-1,并将x打上标记,最后统计前 ...

  9. bzoj3083 遥远的国度 && bzoj3626 LCA (树链剖分)

    今早刷了两道树剖的题目,用时两小时十五分钟= = 树剖的题目代码量普遍120+ 其实打熟练之后是很容易调的,不熟练的话代码量大可能会因为某些小细节调很久 3083:裸树剖+"换根" ...

随机推荐

  1. Alarm机制用于定时服务

    获取一个 AlarmManager 的实例: AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE) ...

  2. JDK各版本新特性浅谈

    JDK 5.0 自动拆装箱 枚举 可变参数 泛型 For -each 内省 静态导入 JDK 6.0 console开发控制台程序 轻量级HTTP ServerAPI 支持脚本语言 使用Compile ...

  3. luogu3375 【模板】KMP字符串匹配

    nxt数组下标从1开始而a,b数组下标从0开始. #include <iostream> #include <cstring> #include <cstdio> ...

  4. flex布局之flex-grow和flex-shrink如何计算

    此文已由作者张含会授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 关于盒模型布局 如何实现两栏布局? (表格) 流式, 浮动, 定位 如何选择? 流式 > 浮动 > ...

  5. Oracle 学习----:创建表(主键自增)

    一.创建表 create table testTable ( Id numbere, name varchar2(100), age number, createTime date, primary ...

  6. java中使用二进制进行权限控制

    基本概念 package test; publicclass Rights { publicstaticvoid main(String[] args) { int a=1; // 001 状态a i ...

  7. 【转】UGUI之用脚本动态的改变Button的背景图片 和 颜色

    http://blog.csdn.net/u014771617/article/details/45102701 public Button button;void Start(){ColorBloc ...

  8. HTML5 新增绘图功能

    <!DOCTYPE html> <html> <head lang="en"> <title></title> < ...

  9. BZOJ 3990: [SDOI2015]排序(搜索+剪枝)

    [SDOI2015]排序 Description 小A有一个1-2^N的排列A[1..2^N],他希望将A数组从小到大排序,小A可以执行的操作有N种,每种操作最多可以执行一次,对于所有的i(1< ...

  10. 【神题】AtCoder 028 C Min Cost Cycle

    TO BE DONE 思维题 十分巧妙的转化