Description

Solution

边分治+边分树合并

这个题很多做法都是启发式合并的复杂度的,都有点卡

以前有个套路叫做线段树合并优化启发式合并,消掉一个 \(log\)

这个题思路类似,建出边分树,通过一些操作把它变成线段树,就可以线段树合并了

首先边分树的相关定理:

如果一棵包含 \(N\) 个结点的树中每个点的度均不大于 \(D\),那么存在一条边,使得分出的两棵子树的结点个数在 \([N/(D+1),N*D/(D+1)]\)

那么边分树的深度和度数是相关的,我们只需要通过加虚点把这棵树变成二叉树就好了

回到这个题:

枚举第二棵树的 \(lca\) , 然后剩下的就是在第二棵树中选出在第一棵树中 \(dep[x]+dep[y]-dep[lca(x,y)]\) 的最大值

我们发现这个要求的东西就是 \(x,y\) 到根的路径的交,所以可以不考虑第一棵树的 \(lca\) 了

其中 \(x,y\) 都来自这个 \(lca\) 的不同子树内

每次插入一个点就像线段树那样更新就行了,不同的是你不能准确定位到这个叶子节点,你需要在 \(build\) 的时候顺便存一下对应关系

枚举第二棵树的 \(lca\) 再合并子树的边分树,顺便更新一下答案就行了

  1. #include<bits/stdc++.h>
  2. #define vc vector<edge>::iterator
  3. #define pb push_back
  4. using namespace std;
  5. typedef long long ll;
  6. const int N=750000,M=8510000,T=N*2;
  7. int n,V,sz[N],sum,son[N]={N},val[T],ls[T],rs[T],dep[N],fa[T],tt=0;
  8. ll f[N][20],dis[N],fl[M],fr[M],ans=0,D;int lm[M],rm[M],rt[N/2],id[M];
  9. struct edge{
  10. int x,v;
  11. edge(){}
  12. edge(int _x,int _v){x=_x;v=_v;}
  13. }q[N];
  14. vector<edge>G1[N],G2[N/2];
  15. inline void add(int x,int y,int z,vector<edge>*G){
  16. G[x].pb(edge(y,z));G[y].pb(edge(x,z));
  17. }
  18. inline void build(int x,int last){
  19. for(vc it=G1[x].begin();it!=G1[x].end();++it){
  20. if(it->x==last)continue;
  21. dis[it->x]=dis[x]+it->v;build(it->x,x);
  22. }
  23. int l=1,r=0;edge u,v;
  24. for(vc it=G1[x].begin();it!=G1[x].end();++it)if(it->x!=last)q[++r]=*it;
  25. while(l+2<=r){
  26. int o=++V;u=q[l++],v=q[l++];
  27. add(o,u.x,u.v,G1);add(o,v.x,v.v,G1);
  28. q[++r]=edge(o,0);
  29. }
  30. vector<edge>().swap(G1[x]);
  31. while(l<=r)add(x,q[l].x,q[l].v,G1),l++;
  32. }
  33. inline void getdis(int x,int last,int d){
  34. for(vc it=G1[x].begin();it!=G1[x].end();++it){
  35. if(it->x==last || it->x==-1)continue;
  36. f[it->x][d]=f[x][d]+it->v;getdis(it->x,x,d);
  37. }
  38. }
  39. inline void getedge(int x,int last,int &ex,int &ey){
  40. sz[x]=1;
  41. for(int i=G1[x].size()-1,u;i>=0;i--){
  42. if((u=G1[x][i].x)==last || u==-1)continue;
  43. getedge(u,x,ex,ey);sz[x]+=sz[u];
  44. if(son[u]<son[ey])ex=x,ey=u;
  45. }
  46. son[x]=abs(sum-2*sz[x]);
  47. }
  48. inline int solve(int x,int S,int d){
  49. if(S==1){dep[x]=d;return x;}
  50. int ex=0,ey=0,o=++V;
  51. getdis(x,x,d);
  52. sum=S;getedge(x,x,ex,ey);
  53. for(vc it=G1[ex].begin();it!=G1[ex].end();++it)
  54. if(it->x==ey){val[o]=it->v;it->x=-1;break;}
  55. for(vc it=G1[ey].begin();it!=G1[ey].end();++it)
  56. if(it->x==ex){it->x=-1;break;}
  57. fa[ls[o]=solve(ex,S-sz[ey],d+1)]=o;
  58. fa[rs[o]=solve(ey,sz[ey],d+1)]=o;
  59. return o;
  60. }
  61. inline int ins(int x){
  62. for(int i=dep[x],u=x,la=x;i>=1;i--){
  63. id[++tt]=fa[x];fl[tt]=fr[tt]=-1ll<<60;
  64. if(ls[fa[x]]==x)fl[tt]=max(fl[tt],dis[u]+f[u][i]),lm[tt]=la;
  65. if(rs[fa[x]]==x)fr[tt]=max(fr[tt],dis[u]+f[u][i]),rm[tt]=la;
  66. la=tt;x=fa[x];
  67. }
  68. return tt;
  69. }
  70. inline int merge(int x,int y){
  71. if(!x||!y)return x+y;
  72. ans=max(ans,(fl[x]+fr[y]+val[id[x]])/2-D);
  73. ans=max(ans,(fl[y]+fr[x]+val[id[x]])/2-D);
  74. fl[x]=max(fl[x],fl[y]);fr[x]=max(fr[x],fr[y]);
  75. lm[x]=merge(lm[x],lm[y]);rm[x]=merge(rm[x],rm[y]);
  76. return x;
  77. }
  78. inline void dfs(int x,int last,ll d){
  79. rt[x]=ins(x);ans=max(ans,dis[x]-d);
  80. for(vc it=G2[x].begin();it!=G2[x].end();++it){
  81. if(it->x==last)continue;
  82. dfs(it->x,x,d+it->v);D=d;
  83. rt[x]=merge(rt[x],rt[it->x]);
  84. }
  85. }
  86. int main(){
  87. freopen("pp.in","r",stdin);
  88. freopen("pp.out","w",stdout);
  89. cin>>n;V=n;
  90. int x,y,z;
  91. for(int i=1;i<n;i++)scanf("%d%d%d",&x,&y,&z),add(x,y,z,G1);
  92. for(int i=1;i<n;i++)scanf("%d%d%d",&x,&y,&z),add(x,y,z,G2);
  93. build(1,1);solve(1,V,0);dfs(1,1,0);
  94. cout<<ans<<endl;
  95. return 0;
  96. }

bzoj 5341: [Ctsc2018]暴力写挂的更多相关文章

  1. BZOJ5341: [Ctsc2018]暴力写挂

    BZOJ5341: [Ctsc2018]暴力写挂 https://lydsy.com/JudgeOnline/problem.php?id=5341 分析: 学习边分治. 感觉边分治在多数情况下都能用 ...

  2. [CTSC2018]暴力写挂——边分树合并

    [CTSC2018]暴力写挂 题面不错 给定两棵树,两点“距离”定义为:二者深度相加,减去两棵树上的LCA的深度(深度指到根节点的距离) 求最大的距离. 解决多棵树的问题就是降维了. 经典的做法是边分 ...

  3. [LOJ#2553][CTSC2018]暴力写挂

    [LOJ#2553][CTSC2018]暴力写挂 试题描述 temporaryDO 是一个很菜的 OIer .在 4 月,他在省队选拔赛的考场上见到了<林克卡特树>一题,其中 \(k = ...

  4. BZOJ5341[Ctsc2018]暴力写挂——边分治+虚树+树形DP

    题目链接: CSTC2018暴力写挂 题目大意:给出n个点结构不同的两棵树,边有边权(有负权边及0边),要求找到一个点对(a,b)满足dep(a)+dep(b)-dep(lca)-dep'(lca)最 ...

  5. [CTSC2018]暴力写挂

    题目描述 www.lydsy.com/JudgeOnline/upload/201805/day1(1).pdf 题解 首先来看这个我们要最大化的东西. deep[u]+deep[v]-deep[lc ...

  6. UOJ400/LOJ2553 CTSC2018 暴力写挂 边分治、虚树

    传送门--UOJ 传送门--LOJ 跟隔壁通道是一个类型的 要求的式子中有两个LCA,不是很方便,因为事实上在这种题目中LCA一般都是枚举的对象-- 第二棵树上的LCA显然是动不了的,因为没有其他的量 ...

  7. 并不对劲的bzoj5341:loj2553:uoj400:p4565:[Ctsc2018]暴力写挂

    题目大意 有两棵\(n\)(\(n\leq366666\))个节点的树,\(T\)和\(T'\),有边权 \(dep(i)\)表示在\(T\)中\(i\)号点到\(1\)号点的距离,\(dep'(i) ...

  8. 题解 「CTSC2018暴力写挂」

    题目传送门 题目大意 给出两个大小为 \(n\) 的树,求出: \[\max\{\text{depth}(x)+\text{depth}(y)-\text{depth}(\text{LCA}(x,y) ...

  9. 【CTSC2018】暴力写挂(边分治,虚树)

    [CTSC2018]暴力写挂(边分治,虚树) 题面 UOJ BZOJ 洛谷 题解 发现第二棵树上的\(LCA\)的深度这玩意没法搞,那么枚举在第二棵树上的\(LCA\). 然后剩下的部分就是\(dep ...

随机推荐

  1. mysql免安装版 安装配置 (转)

    1. 下载MySQL Community Server 5.6.13 2. 解压MySQL压缩包     将以下载的MySQL压缩包解压到自定义目录下,我的解压目录是:     "D:\Pr ...

  2. 拒绝“高冷”词汇!初学C#中的委托

    有一天,你写了好多好多带“形参”的构造函数(就是“方法”,同义),而且需要向这些构造函数里传递同样的“实参”,然后你就憨憨地一个一个函数的调用并赋予同样的“实参”,这一天就这么过去了... 又过了几天 ...

  3. [ASP.NET]ASP.NET中常用的26个优化性能方法

    1. 数据库访问性能优化 数据库的连接和关闭 访问数据库资源需要创建连接.打开连接和关闭连接几个操作.这些过程需要多次与数据库交换信息以通过身份验证,比较耗费服务器资源.ASP.NET中提供了连接池( ...

  4. 双缓冲队列解决WPF界面卡死

    工作中的项目,CS客户端会通过MQ接收前端设备发送的信息,之前测试的时候,由于测试的数据不大,没有进行压力测试,软件可以正常工作,随着项目现场设备数量的增加,CS客户端从MQ中订阅的数据量不断增加,最 ...

  5. WPF画辐射图

    public void WriteLineCircle(double originX, double originY, double r, int lineCount,List<string&g ...

  6. gridview获取选中行索引及当前行数据

    gridview获取选中行索引及当前行数据 一.非直接绑定数据: <!--前台传值--> <asp:TemplateField HeaderText="操作"&g ...

  7. Kettle 使用入门

    Kettle是一款国外开源的ETL工具,纯java编写,可以在Window.Linux.Unix上运行,数据抽取高效稳定. 本文介绍一个入门例子:使用Kettle从动态指定的文件名对应的文本文件里抽取 ...

  8. JavaWeb -学生信息管理实践(JDBC+web+三层架构+DBUtil构造思路)

    前言: 1 该程序使用动态web项目 2 该程序使用SQL server需导入对应包( 具体可看前篇----JDBC的使用) 3 三层架构思想: ①表示层 前台:jsp/html等 作为前台与用户交互 ...

  9. java删除字符串最后一个字符的几种方法

    偶然看到的,记录一下,以免忘记 字符串:string s = "1,2,3,4,5," 目标:删除最后一个 "," 方法:    1.用的最多的是Substri ...

  10. centos7修改默认运行级别的变化

    在学习centos7,视频教学中使用的的centos6,查看权限文件命令为 cat /etc/inittab/ 但是在centos7中输入以下命令会出现这种情况 这个已经不用了,现在修改权限的命令修改 ...