lca的好题!网上用st表和离线解的比较多,用树上倍增也是可以做的

不知道错在哪里,等刷完了这个专题再回来看

题解链接https://blog.csdn.net/Sd_Invol/article/details/9572423

  1. /*
  2. 给一颗点权树,求出一个点对(x,y)之间的max{A,B,C}
  3. A:x到lca路径上的最大差值
  4. B:lca到y路径上的最大差值
  5. C:x到y路径上的最大差值
  6. 需要维护的值,x结点到的祖先,x结点到祖先路径上的最大值,最小值,x结点到路径上的最大收益,最小收益(可以是负数)
  7. 对于每个询问x->y:A:x到祖先的最大收益
  8. B:y到祖先的最小收益的负值
  9. C:x到lca的最大值减去lca到y的最小值
  10. */
  11. #include<iostream>
  12. #include<cstring>
  13. #include<cstdio>
  14. #include<cmath>
  15. #include<algorithm>
  16. using namespace std;
  17. #define maxn 50005
  18. struct Edge{
  19. int x,next;
  20. }e[maxn<<];
  21. int head[maxn],tot,n,q;
  22. inline void addedge(int u,int v){
  23. e[tot].x=v;
  24. e[tot].next=head[u];
  25. head[u]=tot++;
  26. }
  27. int d[maxn],f[maxn][],a[maxn];//深度,祖先,点权
  28. int fm[maxn][],fn[maxn][],sm[maxn][],sn[maxn][];//最大值,最小值,最大收益,最小收益
  29. void init(){
  30. tot=;
  31. memset(head,-,sizeof head);
  32. }
  33. void dfs(int x,int fa,int dep){
  34. d[x]=dep,f[x][]=fa;
  35. for(int i=head[x];i!=-;i=e[i].next)
  36. if(fa!=e[i].x) dfs(e[i].x,x,dep+);
  37. }
  38. int query(int x,int y){
  39. int i,xx=,yy=,X=a[x],Y=a[y];//x侧最大收益,y侧最小收益,x侧最小值,y侧最大值
  40. i=;
  41. while(d[x]!=d[y]){//拉倒同一高度
  42. if(abs(d[x]-d[y]) >= <<i)
  43. if(d[y]<d[x])
  44. xx=max(max(xx,sm[x][i]),fm[x][i]-X),X=min(X,fn[x][i]),x=f[x][i];
  45. else
  46. yy=min(min(yy,sn[y][i]),fn[y][i]-Y),Y=max(Y,fm[y][i]),y=f[y][i];
  47. --i;
  48. }
  49. if(x==y) return max(max(xx,-yy),Y-X);
  50. i=;
  51. while(i>=){
  52. if(f[x][i] && f[y][i] && f[x][i]!=f[y][i]){
  53. xx=max(max(xx,sm[x][i]),fm[x][i]-X),X=min(X,fn[x][i]),x=f[x][i];
  54. yy=min(min(yy,sn[y][i]),fn[y][i]-Y),Y=max(Y,fm[y][i]),y=f[y][i];
  55. }
  56. --i;
  57. }
  58. i=;//这里还要跳一次
  59. xx=max(max(xx,sm[x][i]),fm[x][i]-X),X=min(X,fn[x][i]),x=f[x][i];
  60. yy=min(min(yy,sn[y][i]),fn[y][i]-Y),Y=max(Y,fm[y][i]),y=f[y][i];
  61. return max(max(xx,-yy),Y-X);
  62. }
  63. void work(){
  64. int x,y;
  65. init();
  66. scanf("%d",&n);
  67. for(int i=;i<=n;i++) scanf("%d",&a[i]);
  68. for(int i=;i<n;i++){
  69. scanf("%d%d",&x,&y);
  70. addedge(x,y);addedge(y,x);
  71. }
  72. dfs(,,);
  73. fm[][]=fn[][]=a[];
  74. sm[][]=-<<;sn[][]=<<;
  75. for(int i=;i<=n;i++){//先打初始状态
  76. fm[i][]=max(a[i],a[f[i][]]);//和父亲比较
  77. fn[i][]=min(a[i],a[f[i][]]);
  78. sm[i][]=max(,a[f[i][]]-a[i]);//要么是0,要么赚了钱
  79. sn[i][]=min(,a[f[i][]]-a[i]);//要么是0,要么是亏了钱
  80. }
  81. for(int j=;(<<j)<n;j++)//再打剩下状态
  82. for(int i=;i<=n;i++){
  83. int tmp=f[i][j-];//中间态
  84. f[i][j]=f[tmp][j-];
  85. fm[i][j]=max(fm[i][j-],fm[tmp][j-]);
  86. fn[i][j]=min(fm[i][j-],fm[tmp][j-]);
  87. sm[i][j]=max(max(sm[i][j-],sm[tmp][j-]),fm[tmp][j-]-fn[i][j-]);//最大收益要么是两段间的最大收益,要么是祖先段的最大收益减去子孙段的最小收益
  88. sn[i][j]=min(min(sn[i][j-],sn[tmp][j-]),fn[tmp][j-]-fm[i][j-]);//最小收益相反
  89. }
  90. scanf("%d",&q);
  91. while(q--){
  92. scanf("%d%d",&x,&y);
  93. printf("%d\n",query(x,y));
  94. }
  95. }
  96. int main(){
  97. work();
  98. return ;
  99. }

poj3728 倍增法lca 好题!的更多相关文章

  1. Codeforces 519E A and B and Lecture Rooms [倍增法LCA]

    题意: 给你一棵有n个节点的树,给你m次询问,查询给两个点,问树上有多少个点到这两个点的距离是相等的.树上所有边的边权是1. 思路: 很容易想到通过记录dep和找到lca来找到两个点之间的距离,然后分 ...

  2. 倍增法-lca codevs 1036 商务旅行

    codevs 1036 商务旅行  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description 某首都城市的商人要经常到各城镇去做生意 ...

  3. 倍增法lca

    ][N],siz[N];//rt数组需要在dfs之前置-1. void dfs(int pos,int deep){ dep[pos]=deep; siz[pos]=; for(edge *it=ad ...

  4. poj1470 LCA倍增法

    倍增法模板题 #include<iostream> #include<cstring> #include<cstdio> #include<queue> ...

  5. 最近公共祖先算法LCA笔记(树上倍增法)

    Update: 2019.7.15更新 万分感谢[宁信]大佬,认认真真地审核了本文章,指出了超过五处错误捂脸,太尴尬了. 万分感谢[宁信]大佬,认认真真地审核了本文章,指出了超过五处错误捂脸,太尴尬了 ...

  6. 浅谈倍增法求解LCA

    Luogu P3379 最近公共祖先 原题展现 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入格式 第一行包含三个正整数 \(N,M,S\),分别表示树的结点个数.询问 ...

  7. lca入门———树上倍增法(博文内含例题)

    倍增求LCA: father[i][j]表示节点i往上跳2^j次后的节点 可以转移为 father[i][j]=father[father[i][j-1]][j-1] 整体思路: 先比较两个点的深度, ...

  8. 倍增法求LCA(最近公共最先)

    对于有根树T的两个结点u.v,最近公共祖先x=LCA(u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. 如图,根据定义可以看出14和15的最近公共祖先是10,   15和16的最近公共 ...

  9. hdu2586 lca倍增法

    倍增法加了边的权值,bfs的时候顺便把每个点深度求出来即可 #include<iostream> #include<cstring> #include<cstdio> ...

随机推荐

  1. AtomicInteger和count++的比较

    J2SE 5.0提供了一组atomic class来帮助我们简化同步处理.基本工作原理是使用了同步synchronized的方法实现了对一个long, integer, 对象的增.减.赋值(更新)操作 ...

  2. JDK JRE JVM的关系

    JVM:Java Virtual Machine的缩写,即Java虚拟机 JRE:Java Runtime Environment的缩写,即Java运行环境 JDK:Java Development ...

  3. Linux命令之mkdir

    mkdir命令 用处:创建文件夹 用法:在终端中输入mkdir加上文件夹的名字 示例: (我想创建一个名字为shuyunquan的文件夹)

  4. HTML5视频播放插件Video.js使用详解

    一.Video.js简介 Video.js 是一个开源的 Html5 jquery 视频插件,这个插件可以用来处理 Flash 视频,它还是一个多平台支持的产品. Moreover,YouTube,V ...

  5. 第三次实验计算分段函数 第四次计算分段函数和循环NEW 第五次分支+循环加强版 实验报告

    一.实验题目,设计思路,实现方法 第四次分支+循环 加强版 (2-2计算个人所得税,2-7 装睡,2-8计算天数) 设计思路:2-2 用if-else的语句,与计算分段函数的题类似的做法:2-7 运用 ...

  6. Linux 开机启动图形界面,shell界面

    查看当前启动模式 # systemctl get-default 更改模式命令: systemctl set-default graphical.target由命令行模式更改为图形界面模式 syste ...

  7. Python3之网络爬虫<0>初级

    由于Python3合并URLib与URLlib2统一为URLlib,Python3将urlopen方法放在了urllib.request对象下. 官方文档:https://docs.python.or ...

  8. org.springframework.beans.BeanUtils与org.apache.commons.beanutils.BeanUtils的copyProperties用法区别

    知识点 org.springframework.beans.BeanUtils与org.apache.commons.beanutils.BeanUtils都提供了copyProperties方法,作 ...

  9. mysql 案例 ~ 瘦身mysql系列(1)

    一 简介:这一系列我们要进行如何瘦身mysql 二 目的:通过提高CPU利用率和节约成本,降低数据库容量及I/O负载,从而使数据吞吐率得到显著提高 三 方法: 利用innodb的COMPRESSED ...

  10. vue UI框架

    一.pc端 element UI 饿了么UI支持vue2.x80分优点:组件的API方法.属性等封装的较为完善缺点:样式有些生硬,不够炫酷美观 N3 N3支持vue2.x70分优点:组件操作几乎都有动 ...