题意:给出一个图,先求出最大生成树,然后多次询问树上路径\(u→v\)的有向最大极差\(max(a_i-a_j),i>j\),其中\(i\)和\(j\)指代节点在路径中出现的顺序

极差具有单调性和可相交,因此可以用倍增来合并答案求解

维护变量

\(mx[i][j]\):\(i\)节点到\(i\)的第\(2^j\)个祖先的最大值

\(mn[i][j]\):\(i\)节点到\(i\)的第\(2^j\)个祖先的最小值

\(f[i][j]\):\(i\)节点到\(i\)的第\(2^j\)个祖先的最大极差

\(g[i][j]\):\(i\)的第\(2^j\)个祖先到\(i\)节点的最大极差

每次询问就是\(u,lca(u,v),v\)的分类讨论

答案可能是

\(u→lca(u,v)\)的最大极差

\(lca(u,v)→v\)的最大极差

\(u->lca(u,v)\)的最小值和\(lca(u,v)→v\)的最大值的差

注意查询极差时要额外维护\(u/v\)到当前节点的最大/最小值来合并单链的最优解(留意顺序的先后)

还有是先dfs还是先递推的细节问题(WA成狗)

如果问题带修改那就强上树剖吧

  1. #include<bits/stdc++.h>
  2. #define rep(i,j,k) for(register int i=j;i<=k;i++)
  3. #define rrep(i,j,k) for(register int i=j;i>=k;i--)
  4. #define println(a) printf("%lld\n",(ll)a)
  5. using namespace std;
  6. const int MAXN = 1e5+11;
  7. typedef long long ll;
  8. ll read(){
  9. ll x=0,f=1;register char ch=getchar();
  10. while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  11. while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
  12. return x*f;
  13. }
  14. int to[MAXN<<1],nxt[MAXN<<1],cost[MAXN<<1],head[MAXN],tot;
  15. int pp[MAXN];
  16. int p[MAXN][17],dep[MAXN];
  17. int mn[MAXN][17],mx[MAXN][17];
  18. int f[MAXN][17],g[MAXN][17];
  19. int a[MAXN];
  20. bool vis[MAXN];
  21. struct EDGE{
  22. int from,to,cost;
  23. EDGE(){}
  24. EDGE(int f,int t,int c){
  25. from=f;
  26. to=t;
  27. cost=c;
  28. }
  29. bool operator<(const EDGE &rhs)const{
  30. return cost>rhs.cost;
  31. }
  32. }e[MAXN];
  33. void init(){
  34. memset(head,-1,sizeof head);
  35. memset(f,0,sizeof f);
  36. memset(g,0,sizeof g);
  37. memset(mx,0,sizeof mx);
  38. memset(mn,0x3f,sizeof mn);
  39. memset(vis,0,sizeof vis);
  40. tot=0;
  41. }
  42. void add(int u,int v){
  43. to[tot]=v;
  44. nxt[tot]=head[u];
  45. head[u]=tot++;
  46. }
  47. int find(int x){return x==pp[x]?x:pp[x]=find(pp[x]);}
  48. ll MST(int n,int m){
  49. sort(e+1,e+1+m);
  50. ll ans=0;
  51. rep(i,0,n) pp[i]=i;
  52. rep(i,1,m){
  53. int u=e[i].from;
  54. int v=e[i].to;
  55. int w=e[i].cost;
  56. int aa=find(u),bb=find(v);
  57. if(aa==bb) continue;
  58. pp[aa]=bb;
  59. ans+=1ll*w;
  60. add(u,v); add(v,u);
  61. }
  62. return ans;
  63. }
  64. void dfs(int u,int fa,int d){
  65. dep[u]=d; vis[u]=1;
  66. if(fa==-1) rep(j,0,16) p[u][j]=u,mn[u][j]=mx[u][j]=a[u];
  67. for(int i=head[u];~i;i=nxt[i]){
  68. int v=to[i];
  69. if(v==fa||vis[v]) continue;
  70. rep(j,0,16){
  71. if(j){
  72. p[v][j]=p[p[v][j-1]][j-1];
  73. mx[v][j]=max(mx[v][j-1],mx[p[v][j-1]][j-1]);
  74. mn[v][j]=min(mn[v][j-1],mn[p[v][j-1]][j-1]);
  75. f[v][j]=max(f[v][j-1],f[p[v][j-1]][j-1]);
  76. g[v][j]=max(g[v][j-1],g[p[v][j-1]][j-1]);
  77. f[v][j]=max(f[v][j],mx[p[v][j-1]][j-1]-mn[v][j-1]);
  78. g[v][j]=max(g[v][j],mx[v][j-1]-mn[p[v][j-1]][j-1]);
  79. }else{
  80. p[v][j]=u;
  81. mn[v][j]=min(a[v],a[u]);
  82. mx[v][j]=max(a[v],a[u]);
  83. f[v][j]=a[u]-a[v];
  84. g[v][j]=a[v]-a[u];
  85. }
  86. }
  87. dfs(v,u,d+1);
  88. }
  89. }
  90. int lca(int u,int v){
  91. if(dep[u]<dep[v]) swap(u,v);
  92. int d=dep[u]-dep[v];
  93. rep(j,0,16) if(d>>j&1){
  94. u=p[u][j];
  95. }
  96. if(u==v) return u;
  97. rrep(j,16,0) if(p[u][j]!=p[v][j]){
  98. u=p[u][j];
  99. v=p[v][j];
  100. }
  101. return p[u][0];
  102. }
  103. int MIN(int u,int anc){
  104. int d=dep[u]-dep[anc];
  105. int ans=1<<30;
  106. rep(j,0,16) if(d>>j&1){
  107. ans=min(ans,mn[u][j]);
  108. u=p[u][j];
  109. }
  110. return ans;
  111. }
  112. int MAX(int u,int anc){
  113. int d=dep[u]-dep[anc];
  114. int ans=0;
  115. rep(j,0,16) if(d>>j&1){
  116. ans=max(ans,mx[u][j]);
  117. u=p[u][j];
  118. }
  119. return ans;
  120. }
  121. int LEFT(int u,int anc){
  122. int d=dep[u]-dep[anc];
  123. int ans=0;
  124. int tmin=1<<29;
  125. rep(j,0,16) if(d>>j&1){
  126. ans=max(ans,f[u][j]);
  127. ans=max(ans,mx[u][j]-tmin);
  128. tmin=min(tmin,mn[u][j]);
  129. u=p[u][j];
  130. }
  131. return ans;
  132. }
  133. int RIGHT(int u,int anc){
  134. int d=dep[u]-dep[anc];
  135. int ans=0,tmax=0;
  136. rep(j,0,16) if(d>>j&1){
  137. ans=max(ans,g[u][j]);
  138. ans=max(ans,tmax-mn[u][j]);
  139. tmax=max(tmax,mx[u][j]);
  140. u=p[u][j];
  141. }
  142. return ans;
  143. }
  144. int main(){
  145. int n;
  146. while(~scanf("%d",&n)){
  147. init();
  148. rep(i,1,n) a[i]=read();
  149. int m=read();
  150. rep(i,1,m){
  151. int u=read();
  152. int v=read();
  153. int w=read();
  154. e[i]=EDGE(u,v,w);
  155. }
  156. println(MST(n,m));
  157. rep(i,1,n) if(!vis[i]) dfs(i,-1,1);
  158. int q=read();
  159. while(q--){
  160. int u=read();
  161. int v=read();
  162. int anc=lca(u,v);
  163. int ans=MAX(v,anc)-MIN(u,anc);
  164. ans=max(ans,LEFT(u,anc));
  165. ans=max(ans,RIGHT(v,anc));
  166. println(max(0,ans));
  167. }
  168. }
  169. return 0;
  170. }

ZOJ - 3649 树上倍增的更多相关文章

  1. Social Net ZOJ - 3649

    Social Net ZOJ - 3649 题意: 反正原题题意我是看不懂... 参考:http://www.cnblogs.com/names-yc/p/4922867.html 给出一幅图,求最大 ...

  2. LCA离线Tarjan,树上倍增入门题

    离线Tarjian,来个JVxie大佬博客最近公共祖先LCA(Tarjan算法)的思考和算法实现,还有zhouzhendong大佬的LCA算法解析-Tarjan&倍增&RMQ(其实你们 ...

  3. Codevs 2370 小机房的树 LCA 树上倍增

    题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子, ...

  4. NOIP2013 货车运输 (最大生成树+树上倍增LCA)

    死磕一道题,中间发现倍增还是掌握的不熟 ,而且深刻理解:SB错误毁一生,憋了近2个小时才调对,不过还好一遍AC省了更多的事,不然我一定会疯掉的... 3287 货车运输 2013年NOIP全国联赛提高 ...

  5. HDU 4822 Tri-war(LCA树上倍增)(2013 Asia Regional Changchun)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4822 Problem Description Three countries, Red, Yellow ...

  6. [NOIP2013/Codevs3287]货车运输-最小[大]生成树-树上倍增

    Problem 树上倍增 题目大意 给出一个图,给出若干个点对u,v,求u,v的一条路径,该路径上最小的边权值最大. Solution 看到这个题第一反应是图论.. 然而,任意路径最小的边权值最大,如 ...

  7. 树上倍增求LCA及例题

    先瞎扯几句 树上倍增的经典应用是求两个节点的LCA 当然它的作用不仅限于求LCA,还可以维护节点的很多信息 求LCA的方法除了倍增之外,还有树链剖分.离线tarjan ,这两种日后再讲(众人:其实是你 ...

  8. [树上倍增+二分答案][NOIP2012]运输计划

    题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 公元 2044 年,人类进入了宇宙纪元 L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条航道建立在两个星球之间,这 n-1n− ...

  9. 两种lca的求法:树上倍增,tarjan

    第一种:树上倍增 f[x,k]表示x的2^k辈祖先,即x向根结点走2^k步达到的结点. 初始条件:f[x][0]=fa[x] 递推式:f[x][k]=f[ f[x][k-1] ][k-1] 一次bfs ...

随机推荐

  1. CentOS 7 升级内核 Kernel

    安装kernel 首先安装elrepo rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org rpm -Uvh http://www.e ...

  2. 项目中遇到的死锁问题: Lock wait timeout exceeded; try restarting transaction

    最近项目中频繁出现  Lock wait timeout exceeded; try restarting transaction这个错误,把我们弄得痛苦不堪啊,为了解决问题,上网上找好多资料,终于把 ...

  3. android session解析

    最近在开发项目的过程中,遇到Android与web服务器要在同一session下通信的问题. 在解决问题前先回顾下Session与Cookie: Cookie和Session都为了用来保存状态信息,都 ...

  4. a 标签 name 属性 页面定位 (二)

    <a href="to_url#somewhere">名字</a> <a name="somewhere">名字</a ...

  5. 编写高质量代码改善C#程序的157个建议——建议137:委托和事件类型应添加上级后缀

    建议137:委托和事件类型应添加上级后缀 委托类型本身是一个类,考虑让派生类的名字以基类名字作为后缀.事件类型是一类特殊的委托,所以事件类型也遵循本建议. 委托和事件的正确的命名方式有: public ...

  6. 【小梅哥FPGA进阶教程】第十三章 四通道数字电压表

    十三.四通道数字电压表 本文由山东大学研友袁卓贡献,特此感谢 实验目的 设计一个四通道的数字电压表 实验平台 芯航线FPGA核心板.AD/DA模块 实验现象 实现一个四通道的数字电压表,其中可以用按键 ...

  7. SIP协议整理

    本文记录开发.实现IMS项目时,整理的SIP协议基础知识:若有侵权,请告之. SIP协议 1.      SIP协议简介 SIP是一个应用层的控制协议,可以用来建立.修改.和终止多媒体会话(或者会议) ...

  8. jquery库与其他库冲突的问题解决-jquery.noConflict()

    在使用jQuery开发的时候,可能还会使用到其他的JS库,比如Prototype,但多库共存时可能会发生冲突:若是发生冲突后,可以通过以下几种方案进行解决: 一. jQuery库在其他库之前导入,直接 ...

  9. kali 下 apache 配置文件

    默认的可执行文件 /usr/sbin/apache2 root@ty:/etc/init.d# netstat -anp |grep apache tcp6 ::: :::* LISTEN /apac ...

  10. 理解ASP.NET MVC引擎处理模型字符串的默认行为,涉及Html.Raw()和HttpUtility.HtmlDecode()

    MVC引擎默认会将Model属性值中包含的html字符串做encode,所以如属性中包含类似 <br> 这样的标记,MVC引擎会将它们转换成html实体码 %3Cbr%3E 所以1:在编辑 ...