题目

描述

​ 有两棵树\(T\)和\(T'\),节点个数都为\(n\),根节点都为\(1\)号节点;

​ 求两两点之间

\[
\begin{align}
depth(x) + depth(y) - depth(LCA(x,y)) - depth'(LCA'(x,y))
\end{align}
\\
其中depth(x)为x和1号节点的树上距离
\\

\]

​ 的最大值;

范围

​ $1 \le n \le 366666 $ ;

题解

  • 原式 = \(\frac{(dep(x) + dep(y) + dis(x,y)) }{2} -dep'(x,y)\) ;

  • 枚举第二颗树的节点\(u\),只需要查询\(u\)的各个子树之间的答案;

  • 考虑查询一个对很多点的左边的式子时,可以直接用边分治;

  • 询问两个子树之间的答案也可以用边分治,复杂度是\(O(n^2log \ n)\)的;

  • 注意到边分树是一个二叉树的结构,直接采用线段树和并的写法合并;

  • 学习了一下边分治:

    • 每次选择一条边\((u,v)\),使得两边的子树最大\(size\)最小,不断分治;
    • 考虑直接分析复杂度:
      • 这部分理论是\(cjl\)老师在济南讲课的时候说的,网上说了这个的好少。。。。
      • 设整棵树最大的度数为\(D\),\(u\)的子树大小为\(s\),不妨令:\(u \ge n - s\);
      • \(u\)的子树大小最大的儿子的子树大小是\(p\);
      • 直接有:$p \ge \frac{s-1}{D-1} $ ;
      • 同时由于\((u,v)\)是最优的决策,一定有:$n - p \ge s $;
      • 解得:$s \le \frac{n(D-1) + 1}{D} $ ;
      • 意思是每次的联通块大小是以约\(\frac{D-1}{D}\)的倍数缩小;
    • 当\(D\)是个常数时复杂度是\(log\)的,所以直接考虑将图变成一颗二叉树;
      • 黑色的点和边代表原图中的边,绿色的点和边代表虚点和虚边;

        -新图的大小为原图的两倍;

      • 注意对边权和点权的修改因题而异;

  • 另外意外看到\(dsu \ on \ tree\) ;

    • 适用于一些删除比较麻烦的树上数据结构,不支持修改;
    • \(dfs\)并树剖,当一个节点做完了存储了子树的信息;
    • 假设我们有一个支持插入和完全清零的全局数据结构\(Ds\),一次操作是\(O(Ds)的\);
    • 每次先做轻儿子,做完后枚举子树节点暴力清空和轻儿子子树有关的\(Ds\)信息;
    • 所以当做完\(u\)的所有儿子回溯到\(u\)时,\(Ds\)中只存在\(u\)的重儿子的子树的影响;
    • 再做一遍所有轻儿子的子树,插入到\(Ds\)中去;
    • 当一个点被遍历的时候一定是出现了一条轻链;
    • 一个点向上的轻链个数为\(O(log \ n)\)的,所以为\(O(n log \ n \ Ds)\);
    • 套用到本题得到一个\(O(n log^2 \ n)\)的做法;

//这份代码过不了uoj的extra test ,luogu上会T一个点,暂时还没有修改;

include<bits/stdc++.h>

define mk make_pair

define fi first

define se second

define pb push_back

define inf 1e18

define ll long long

using namespace std;

const int N=366666<<2,M=22;

int n,o,hd[N],cnt,rt,mn,Rt[N],ls[N],rs[N],fa[N];

int vis[N],size,sz[N],d[N],tot,lc[NM],rc[NM];

ll dep[N],dis[M][N],val[N],mxl[NM],mxr[NM],wv[NM],ans=-inf;

struct Edge{int v,nt,w;}E[N];

typedef pair<int,int>pii;

vectorg[N];

char gc(){

static char
p1,p2,s[1000000];

if(p1p2)p2=(p1=s)+fread(s,1,1000000,stdin);

return(p1p2)?EOF:
p1++;

}

int rd(){

int x=0,f=1;char c=gc();

while(c<'0'||c>'9'){if(c'-')f=-1;c=gc();}

while(c>='0'&&c<='9'){x=x10+c-'0';c=gc();}

return x
f;

}

void upd(ll&x,ll y){if(x<y)x=y;}

void adde(int u,int v,int w){

E[o]=(Edge){v,hd[u],w};hd[u]=o++;

E[o]=(Edge){u,hd[v],w};hd[v]=o++;

}

void dfs1(int u,int F){

for(int i=0,lst=0;i<(int)g[u].size();++i){

int v=g[u][i].fi,w=g[u][i].se;

if(vF)continue;

dep[v]=dep[u]+w;dfs1(v,u);

if(!lst){adde(u,v,w);lst=u;continue;}

adde(lst,++cnt,0);adde(cnt,v,w);lst=cnt;

}

}

void get_rt(int u,int F){

sz[u]=1;

for(int i=hd[u];~i;i=E[i].nt){

int v=E[i].v;

if(vis[i]||vF)continue;

get_rt(v,u);sz[u]+=sz[v];

int t=max(size-sz[v],sz[v]);

if(mn>=t)rt=i,mn=t;

}

}

void calc(int d,int u,int F,ll now){

dis[d][u]=now;

for(int i=hd[u];~i;i=E[i].nt){

int v=E[i].v;

if(vis[i]||vF)continue;

calc(d,v,u,now+E[i].w);

}

}

int solve(int u,int F){

if(size1){fa[u]=F;return u;}

int now=++cnt;

rt=-1;mn=size;get_rt(u,0);

val[now]=E[rt].w;

vis[rt]=vis[rt^1]=1;

d[now]=d[fa[now]=F]+1;

int v1=E[rt].v,v2=E[rt^1].v;

calc(d[now],v1,0,0);

calc(d[now],v2,0,0);

size-=sz[v1];rs[now]=solve(v2,now);

size=sz[v1];ls[now]=solve(v1,now);

return now;

}

int ins(int x){

for(int u=fa[x],v=x,lst=0;u;v=u,u=fa[u]){

wv[++tot]=val[u];mxl[tot]=mxr[tot]=-inf;

if(ls[u]v)mxl[tot]=dep[x]+dis[d[u]][x],lc[tot]=lst;

else mxr[tot]=dep[x]+dis[d[u]][x],rc[tot]=lst;

lst=tot;

}

return tot;

}

int merge(int x,int y,ll&tmp){

if(!x||!y)return x+y;

upd(tmp,wv[x]+max(mxl[x]+mxr[y],mxl[y]+mxr[x]));

mxl[x]=max(mxl[x],mxl[y]);

mxr[x]=max(mxr[x],mxr[y]);

lc[x]=merge(lc[x],lc[y],tmp);

rc[x]=merge(rc[x],rc[y],tmp);

return x;

}

void dfs2(int u,int F,ll now){

Rt[u]=ins(u);

upd(ans,dep[u]-now);

ll tmp=-inf;

for(int i=hd[u];~i;i=E[i].nt){

int v=E[i].v;

if(v==F)continue;

dfs2(v,u,now+E[i].w);

Rt[u]=merge(Rt[u],Rt[v],tmp);

}

upd(ans,(tmp>>1)-now);

}

int main(){

// freopen("1.in","r",stdin);

// freopen("1.out","w",stdout);

cnt=n=rd();

memset(hd,-1,sizeof(hd));

for(int i=1,u,v,w;i<n;++i){

u=rd(),v=rd(),w=rd();

g[u].pb(mk(v,w));

g[v].pb(mk(u,w));

}

dfs1(1,0);

mxl[0]=mxr[0]=wv[0]=-inf;

size=cnt;solve(1,0);

o=0;memset(hd,-1,sizeof(hd));

for(int i=1;i<n;++i){

int u=rd(),v=rd(),w=rd();

adde(u,v,w);

}

dfs2(1,0,0);

cout<<ans<<endl;

return 0;

}

【学习笔记 边分树】【uoj400】【CTSC2018】暴力写挂的更多相关文章

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

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

  2. BZOJ5341: [Ctsc2018]暴力写挂

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

  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. 并不对劲的bzoj5341:loj2553:uoj400:p4565:[Ctsc2018]暴力写挂

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

  6. [CTSC2018]暴力写挂

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

  7. bzoj 5341: [Ctsc2018]暴力写挂

    Description Solution 边分治+边分树合并 这个题很多做法都是启发式合并的复杂度的,都有点卡 以前有个套路叫做线段树合并优化启发式合并,消掉一个 \(log\) 这个题思路类似,建出 ...

  8. 题解 「CTSC2018暴力写挂」

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

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

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

随机推荐

  1. MySQL数据库对象-索引

    1. 概述2. 索引分类2.1 不同索引的概念2.1.1 普通索引2.1.2 唯一索引2.1.3 全文索引2.1.4 多列索引3. 索引操作3.1 普通索引3.1.1 创建表时创建普通索引3.1.2 ...

  2. sudo 与输出重定向

    本文介绍如何使用 sudo 将输出重定向到当前用户没有权限的文件.注意:本文中 demo 的演示环境为 ubuntu 18.04. Permission denied 问题 如果当前用户没有某个文件的 ...

  3. 《坦克世界》1.0+:使用 CPU 优化的图形和物理丰富用户体验

    本文以<坦克世界>为例,介绍 Wargaming 使用 CPU 多核和 CPU 单指令多数据 (SIMD) 功能显著提升游戏沉浸式体验的创新方法.我们以英特尔® 线程构建模块(英特尔® T ...

  4. Centos7系统下修改主机名操作笔记

    习惯了在Centos6系统下修改主机名的操作,但是Centos7下修改主机名的操作却大不相同!操作笔记如下: 在CentOS中,有三种定义的主机名:静态的(static),瞬态的(transient) ...

  5. 10 分钟理解 BFC 原理

    一.常见定位方案 在讲 BFC 之前,我们先来了解一下常见的定位方案,定位方案是控制元素的布局,有三种常见方案: 普通流 (normal flow) 在普通流中,元素按照其在 HTML 中的先后位置至 ...

  6. SQL Server扩充表字段长度,引发的意外KILLED/ROLLBACK

    这一段时间,因为系统升级,新系统产生的数据长度,比原来的数据长度要长,所以说要扩充一下字段长度. ) --修改字段长度sql 在执行的时候,有这样一个情况. 例如Student表的Name字段长度是n ...

  7. 生产者消费者模式 php 【转】

    在工作中常常听到某某大牛之间的交谈会涉及到,xx消费者啊啥的,到底什么大牛之间讲的是什么? 这篇文章主要解决三个问题: 1.到底什么是生产者和消费者,以及它们之间的故事 2.它们之间靠什么交流 3.应 ...

  8. Linux内核第六节 20135332武西垚

    如何描述一个进程:进程描述符的数据结构: 如何创建一个进程:内核是如何执行的,以及新创建的进程从哪里开始执行: 使用gdb跟踪新进程的创建过程. 进程的描述 操作系统三大功能: 进程管理(最核心最基础 ...

  9. Cron任务调度CronNET

    Cron任务调度CronNET 阅读目录 1.Cron介绍和工具 2.CronNET介绍和使用 3.cron-expression-descriptor使用 4.资源 如果用知乎,可以关注专栏:.NE ...

  10. Cron Expression的用途

    对于一些MIS系统,DeadLine,需要用户自己制定事件规则,Cron Expression应该可以派上用场. Cron Maker: http://www.cronmaker.com/