题目链接

  不会换根从暑假开始就困扰我了……拖到现在……

  会了还是很激动的。

  换根操作事实上不需要(也不能)改树剖本来的dfs序……只是在query上动动手脚……

  设全树的集合为G,以root为根,u在原根到新根的链上的子树集合为G',则有查询区间=G-G'……

  然后查询的时候就查G-G'就行

  

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cctype>
  4. #include<algorithm>
  5. #include<cstring>
  6. #define left (rt<<1)
  7. #define right (rt<<1|1)
  8. #define mid ((l+r)>>1)
  9. #define lson l,mid,left
  10. #define rson mid+1,r,right
  11. #define maxn 100020
  12. using namespace std;
  13. inline long long read(){
  14. long long num=,f=;
  15. char ch=getchar();
  16. while(!isdigit(ch)){
  17. if(ch=='-') f=-;
  18. ch=getchar();
  19. }
  20. while(isdigit(ch)){
  21. num=num*+ch-'';
  22. ch=getchar();
  23. }
  24. return num*f;
  25. }
  26.  
  27. struct Edge{
  28. int next,to;
  29. }edge[maxn*];
  30. int head[maxn],num;
  31. inline void add(int from,int to){
  32. edge[++num]=(Edge){head[from],to};
  33. head[from]=num;
  34. }
  35.  
  36. int tree[maxn*];
  37. int tag[maxn*];
  38. int size[maxn];
  39. int deep[maxn];
  40. int son[maxn];
  41. int father[maxn];
  42. int top[maxn];
  43. int dfn[maxn];
  44. int back[maxn],ID;
  45. int q[maxn];
  46. int s[maxn][];
  47. int n,m;
  48.  
  49. void find(int x,int fa){
  50. deep[x]=deep[fa]+; size[x]=;
  51. for(int i=head[x];i;i=edge[i].next){
  52. int to=edge[i].to;
  53. if(to==fa) continue;
  54. father[to]=x;
  55. s[to][]=x;
  56. find(to,x);
  57. size[x]+=size[to];
  58. if(son[x]==||size[son[x]]<size[to]) son[x]=to;
  59. }
  60. }
  61.  
  62. void unionn(int x,int Top){
  63. dfn[x]=++ID; back[ID]=x;
  64. top[x]=Top;
  65. if(!son[x]) return;
  66. unionn(son[x],Top);
  67. for(int i=head[x];i;i=edge[i].next){
  68. int to=edge[i].to;
  69. if(to==father[x]||to==son[x]) continue;
  70. unionn(to,to);
  71. }
  72. }
  73.  
  74. inline void pushup(int rt){
  75. tree[rt]=min(tree[left],tree[right]);
  76. }
  77.  
  78. void pushdown(int rt){
  79. if(tag[rt]==-) return;
  80. tag[left]=tag[right]=tag[rt];
  81. tree[left]=tree[right]=tag[rt];
  82. tag[rt]=-;
  83. return;
  84. }
  85.  
  86. void build(int l,int r,int rt){
  87. tag[rt]=-;
  88. if(l==r){
  89. tree[rt]=q[back[l]];
  90. return;
  91. }
  92. build(lson);
  93. build(rson);
  94. pushup(rt);
  95. }
  96.  
  97. void memseg(int from,int to,int num,int l,int r,int rt){
  98. if(from<=l&&to>=r){
  99. tree[rt]=tag[rt]=num;
  100. //printf("%d %d l=%d r=%d %d\n",from,to,l,r,num);
  101. return;
  102. }
  103. pushdown(rt);
  104. if(from<=mid) memseg(from,to,num,lson);
  105. if(to>mid) memseg(from,to,num,rson);
  106. pushup(rt);
  107. return;
  108. }
  109.  
  110. int query(int from,int to,int l,int r,int rt){
  111. if(from<=l&&to>=r) return tree[rt];
  112. pushdown(rt);
  113. int ans=0x7fffffff;
  114. if(from<=mid) ans=min(ans,query(from,to,lson));
  115. if(to>mid) ans=min(ans,query(from,to,rson));
  116. return ans;
  117. }
  118.  
  119. int root;
  120.  
  121. void update(int from,int to,int num){
  122. while(top[from]!=top[to]){
  123. if(deep[top[from]]<deep[top[to]]) swap(from,to);
  124. memseg(dfn[top[from]],dfn[from],num,,n,);
  125. from=father[top[from]];
  126. }
  127. if(deep[from]>deep[to]) swap(from,to);
  128. memseg(dfn[from],dfn[to],num,,n,);
  129. return;
  130. }
  131.  
  132. int LCA(int from,int to){
  133. if(deep[from]<deep[to]) swap(from,to);
  134. int f=deep[from]-deep[to];
  135. for(int i=;(<<i)<=f;++i)
  136. if(f&(<<i)) from=s[from][i];
  137. if(from==to) return from;
  138. for(int i=;i>=;--i){
  139. if(s[from][i]==s[to][i]) continue;
  140. from=s[from][i];
  141. to=s[to][i];
  142. }
  143. return s[from][];
  144. }
  145.  
  146. inline void prepare(){
  147. for(int j=;j<=;++j)
  148. for(int i=;i<=n;++i) s[i][j]=s[s[i][j-]][j-];
  149. }
  150.  
  151. int ask(int o){
  152. if(root==) return query(dfn[o],dfn[o]+size[o]-,,n,);
  153. int lca=LCA(root,o);
  154. if(lca!=o) return query(dfn[o],dfn[o]+size[o]-,,n,);
  155. else{
  156. int now=root;
  157. for(int i=;i>=;--i)
  158. if(deep[s[now][i]]>deep[o]) now=s[now][i];
  159. int ans=0x7fffffff;
  160. if(dfn[now]>) ans=min(ans,query(,dfn[now]-,,n,));
  161. if(dfn[now]+size[now]<=n) ans=min(ans,query(dfn[now]+size[now],n,,n,));
  162. return ans;
  163. }
  164. }
  165.  
  166. int main(){
  167. n=read(),m=read();
  168. for(int i=;i<n;++i){
  169. int from=read(),to=read();
  170. add(from,to);
  171. add(to,from);
  172. }
  173. for(int i=;i<=n;++i) q[i]=read();
  174. root=read();
  175. find(,);
  176. unionn(,);
  177. build(,n,);
  178. prepare();
  179. for(int i=;i<=m;++i){
  180. int opt=read();
  181. if(opt==) root=read();
  182. else if(opt==){
  183. int x=read(),y=read(),z=read();
  184. update(x,y,z);
  185. }
  186. else{
  187. int x=read();
  188. printf("%d\n",ask(x));
  189. }
  190. }
  191. return ;
  192. }
  193. /*
  194. 10 10
  195. 1 2
  196. 2 3
  197. 2 4
  198. 1 5
  199. 5 6
  200. 5 10
  201. 5 7
  202. 7 8
  203. 7 9
  204. 5 1 2 3 6 4 7 8 9 10
  205. 1
  206. */

  话说写博客超简略的我简直是业界毒瘤啊……

【Luogu】P3979遥远的国度(树链剖分)的更多相关文章

  1. 洛谷P3979 遥远的国度 树链剖分+分类讨论

    题意:给出一棵树,这棵树每个点有权值,然后有3种操作.操作一:修改树根为rt,操作二:修改u到v路径上点权值为w,操作三:询问以rt为根x子树的最小权值. 解法:如果没有修改树根操作那么这题就是树链剖 ...

  2. [luogu P3384] [模板]树链剖分

    [luogu P3384] [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点 ...

  3. BZOJ 3083 遥远的国度 树链剖分

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 797  Solved: 181[Submit][Status] Descrip ...

  4. BZOJ 3083 遥远的国度(树链剖分+LCA)

    Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...

  5. 【bzoj3083】遥远的国度 树链剖分+线段树

    题目描述 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn ...

  6. BZOJ 3083: 遥远的国度(树链剖分+DFS序)

    可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...

  7. BZOJ 3083 遥远的国度 树链剖分+线段树

    有换根的树链剖分的裸题. 在换根的时候注意讨论. 注意数据范围要开unsigned int或longlong #include<iostream> #include<cstdio&g ...

  8. 【Luogu P3384】树链剖分模板

    树链剖分的基本思想是把一棵树剖分成若干条链,再利用线段树等数据结构维护相关数据,可以非常暴力优雅地解决很多问题. 树链剖分中的几个基本概念: 重儿子:对于当前节点的所有儿子中,子树大小最大的一个儿子就 ...

  9. BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 1280 MBSubmit: 3127  Solved: 795[Submit][Status][Discu ...

  10. luoguP3979 遥远的国度 树链剖分

    \(1, 2\)操作没什么好说的 对于\(3\)操作,分三种情况讨论下 \(id = rt\)的情况下,查整棵树的最小值即可 如果\(rt\)在\(1\)号点为根的情况下不在\(id\)的子树中,那么 ...

随机推荐

  1. MovieReview—Kingsman THE SECRET SERVICE(王牌特工之特工学院)

    Brain Storming         Mr. Valentine's Day see excess human beings as the Earth's virus and try to e ...

  2. ThinkPHP笔记——开启debug调试模式

    debug+trace模式可以查看开发过程中TP的错误信息,可以更好地帮助开发者debug.但是debug模式的开启还不是简单的在配置文件中中设置就可以的,经过查资料摸索,找到一种有效的方法. 首先在 ...

  3. Spark源码分析之-Storage模块

    原文链接:http://jerryshao.me/architecture/2013/10/08/spark-storage-module-analysis/ Background 前段时间琐事颇多, ...

  4. 【转】 iOS学习之NSBundle介绍和使用

    bundle是一个目录,其中包含了程序会使用到的资源.这些资源包含了如图像,声音,编译好的代码,nib文件(用户也会把bundle称为plug-in).对应bundle, cocoa提供了类NSBun ...

  5. solver

    slover中有type,用于优化算法的选择,有6种: Stochastic Gradient Descent (type: “SGD”), AdaDelta (type: “AdaDelta”), ...

  6. BCB:Windows消息处理

    Windows消息处理 BCB 本文研究了BCB中的消息处理机制,在此基础上提出了处理Windows消息和自定义消息响应的方法和建立动态和静态消息映射的技巧. C++ Builder作为一种RAD方式 ...

  7. helm install

    reference 前提:已安装k8s:v1.10.4 helm install on master(无需下载官方tar包) 链接:https://pan.baidu.com/s/1Ji3Ru1pTQ ...

  8. springmvc的第一个程序

    文中用的框架版本:spring 3,hibernate 3,没有的,自己上网下. web.xml配置: <?xml version="1.0" encoding=" ...

  9. 抓取oracle建表语句及获取建表ddl语句

    抓取oracle建表语句及获取建表ddl语句 1.抓取代码如下: 1.1.产生表的语法资料 DECLARE-- v_notPartTable VARCHAR2(1000):= '&2'; -- ...

  10. Android读书笔记四

    第四章 这是一次源代码之旅,学到了如何下载和编译Android源代码和Linux内核源代码.来详细阐述一下一些具体过程 一.Android源代码下载环境 1.安装下载Android源代码的环境配置 ( ...