锟题x2

以下用$a\rightarrow b$表示端点为$a,b$的链

把式子写成$(h_1(x)+h_1(y)-h_1(lca))-h_2(lca')$,第一部分就是$x\rightarrow rt$和$y\rightarrow rt$的并的总长

考虑对第一棵树边分治,假设分治到$(u,v)$,我们想要统计所有跨过$(u,v)$的$x\rightarrow y$

设在树$1$上$fa_v=u$,对于$u$这边的点$x$,令$f_x=-\infty,g_x=dis(x,u\rightarrow rt)$,对$v$这边的点$y$,令$f_y=h_1(y),g_y=-\infty$,那么$h_1(x)+h_1(y)-h_1(lca)=g_x+f_y$(将另外的$f,g$设为$-\infty$是为了防止统计到不跨过$(u,v)$的情况)

所以我们可以将当前分治范围内的点拿出来在树$2$上建虚树,在虚树上统计答案即可

最后不要忘了统计$x=y$的答案...

#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int inf=2147483647;
const ll linf=922337203685477580ll;
int n;
struct pr{
	int to,v;
	pr(int a=0,int b=0){to=a;v=b;}
};
struct tree1{
	int h[733340],nex[1466670],to[1466670],v[1466670],M;
	vector<pr>g[366670];
	void ins(int a,int b,int c){
		M++;
		to[M]=b;
		v[M]=c;
		nex[M]=h[a];
		h[a]=M;
	}
	void add(int a,int b,int c){
		ins(a,b,c);
		ins(b,a,c);
	}
	int N;
	void dfs(int fa,int x){
		vector<pr>::iterator it;
		int p=0;
		for(it=g[x].begin();it!=g[x].end();it++){
			if(it->to!=fa){
				if(p){
					N++;
					add(p,N,0);
					add(N,it->to,it->v);
					p=N;
				}else{
					add(x,it->to,it->v);
					p=x;
				}
			}
		}
		for(it=g[x].begin();it!=g[x].end();it++){
			if(it->to!=fa)dfs(x,it->to);
		}
	}
	ll dis[733340];
	int fa[733340],dep[733340];
	void dfs(int x){
		dep[x]=dep[fa[x]]+1;
		for(int i=h[x];i;i=nex[i]){
			if(to[i]!=fa[x]){
				fa[to[i]]=x;
				dis[to[i]]=dis[x]+v[i];
				dfs(to[i]);
			}
		}
	}
	void gao(){
		int i,x,y,z;
		for(i=1;i<n;i++){
			scanf("%d%d%d",&x,&y,&z);
			g[x].push_back(pr(y,z));
			g[y].push_back(pr(x,z));
		}
		M=1;
		N=n;
		dfs(0,1);
		dfs(1);
	}
}t1;
struct tree2{
	int h[366670],nex[733340],to[733340],v[733340],M;
	void add(int a,int b,int c){
		M++;
		to[M]=b;
		v[M]=c;
		nex[M]=h[a];
		h[a]=M;
	}
	int dfn[366670],mn[733340][20],dep[366670],lg[733340];
	ll dis[366670];
	void dfs(int fa,int x){
		dfn[x]=++M;
		mn[M][0]=x;
		dep[x]=dep[fa]+1;
		for(int i=h[x];i;i=nex[i]){
			if(to[i]!=fa){
				dis[to[i]]=dis[x]+v[i];
				dfs(x,to[i]);
				mn[++M][0]=x;
			}
		}
	}
	int qmin(int x,int y){return dep[x]<dep[y]?x:y;}
	int query(int l,int r){
		int k=lg[r-l+1];
		return qmin(mn[l][k],mn[r-(1<<k)+1][k]);
	}
	int lca(int x,int y){
		if(dfn[x]>dfn[y])swap(x,y);
		return query(dfn[x],dfn[y]);
	}
	void gao(){
		int i,j,x,y,z;
		for(i=1;i<n;i++){
			scanf("%d%d%d",&x,&y,&z);
			add(x,y,z);
			add(y,x,z);
		}
		M=0;
		dfs(0,1);
		for(j=1;j<20;j++){
			for(i=1;i+(1<<j)-1<=M;i++)mn[i][j]=qmin(mn[i][j-1],mn[i+(1<<(j-1))][j-1]);
		}
		for(i=2;i<=M;i++)lg[i]=lg[i>>1]+1;
	}
}t2;
bool cmp(int x,int y){return t2.dfn[x]<t2.dfn[y];}
bool vis[1466670];
int siz[733340],p[366670],M;
void dfs1(int fa,int x){
	if(x<=n)p[++M]=x;
	siz[x]=1;
	for(int i=t1.h[x];i;i=t1.nex[i]){
		if(!vis[i]&&t1.to[i]!=fa){
			dfs1(x,t1.to[i]);
			siz[x]+=siz[t1.to[i]];
		}
	}
}
int al,mn,cn;
void dfs2(int fa,int x){
	for(int i=t1.h[x];i;i=t1.nex[i]){
		if(!vis[i]&&t1.to[i]!=fa){
			dfs2(x,t1.to[i]);
			if(abs(al-2*siz[t1.to[i]])<mn){
				mn=abs(al-2*siz[t1.to[i]]);
				cn=i;
			}
		}
	}
}
ll f[733340],g[733340];
void dfs3(int fa,int x,ll d){
	g[x]=d;
	f[x]=-linf;
	for(int i=t1.h[x];i;i=t1.nex[i]){
		if(!vis[i]&&t1.to[i]!=fa)dfs3(x,t1.to[i],t1.to[i]==t1.fa[x]?0:d+t1.v[i]);
	}
}
void dfs4(int fa,int x){
	f[x]=t1.dis[x];
	g[x]=-linf;
	for(int i=t1.h[x];i;i=t1.nex[i]){
		if(!vis[i]&&t1.to[i]!=fa)dfs4(x,t1.to[i]);
	}
}
ll ans;
struct vtree{
	int h[366670],nex[366670],to[366670],M;
	void add(int a,int b){
		M++;
		to[M]=b;
		nex[M]=h[a];
		h[a]=M;
	}
	void dfs(int x){
		for(int i=h[x];i;i=nex[i]){
			dfs(to[i]);
			ans=max(ans,max(f[x]+g[to[i]],g[x]+f[to[i]])-t2.dis[x]);
			f[x]=max(f[x],f[to[i]]);
			g[x]=max(g[x],g[to[i]]);
		}
		h[x]=0;
	}
	void clear(int x){
		f[x]=g[x]=-linf;
		for(int i=h[x];i;i=nex[i])clear(to[i]);
	}
}vt;
int st[366670],tp;
void insert(int x){
	if(!tp){
		st[++tp]=x;
		return;
	}
	int l=t2.lca(x,st[tp]);
	while(tp>1&&t2.dep[st[tp-1]]>t2.dep[l]){
		vt.add(st[tp-1],st[tp]);
		tp--;
	}
	if(t2.dep[st[tp]]>t2.dep[l]){
		vt.add(l,st[tp]);
		tp--;
	}
	if(t2.dep[st[tp]]<t2.dep[l])st[++tp]=l;
	st[++tp]=x;
}
void build(){
	int i;
	sort(p+1,p+M+1,cmp);
	tp=0;
	vt.M=0;
	for(i=1;i<=M;i++)insert(p[i]);
	for(i=1;i<tp;i++)vt.add(st[i],st[i+1]);
}
void solve(int x){
	int y;
	M=0;
	dfs1(0,x);
	al=siz[x];
	mn=inf;
	cn=0;
	dfs2(0,x);
	if(cn==0)return;
	vis[cn]=vis[cn^1]=1;
	x=t1.to[cn];
	y=t1.to[cn^1];
	if(t1.dep[x]>t1.dep[y])swap(x,y);
	build();
	vt.clear(st[1]);
	dfs3(0,x,0);
	dfs4(0,y);
	vt.dfs(st[1]);
	solve(x);
	solve(y);
}
int main(){
	scanf("%d",&n);
	t1.gao();
	t2.gao();
	ans=-linf;
	solve(1);
	for(int i=1;i<=n;i++)ans=max(ans,t1.dis[i]-t2.dis[i]);
	printf("%lld",ans);
}

[LOJ2553]暴力写挂的更多相关文章

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

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

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

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

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

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

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

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

  5. BZOJ5341: [Ctsc2018]暴力写挂

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

  6. Loj #2553. 「CTSC2018」暴力写挂

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

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

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

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

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

  9. LOJ#2553 暴力写挂

    题意:给定两棵树T1,T2,求d1[x] + d1[y] - d1[lca1(x, y)] - d2[lca2(x, y)]的最大值. 解:考虑把上面这个毒瘤东西化一下.发现它就是T1中x,y到根的路 ...

随机推荐

  1. Spring cookie 实战(山东数漫江湖)

    Cookie是什么 简单来说,cookie就是浏览器储存在用户电脑上的一小段文本文件.cookie 是纯文本格式,不包含任何可执行的代码.一个web页面或服务器告知浏览器按照一定规范来储存这些信息,并 ...

  2. NYOJ 1237 最大岛屿 (深搜)

    题目链接 描述 神秘的海洋,惊险的探险之路,打捞海底宝藏,激烈的海战,海盗劫富等等.加勒比海盗,你知道吧?杰克船长驾驶着自己的的战船黑珍珠1号要征服各个海岛的海盜,最后成为海盗王.  这是一个由海洋. ...

  3. SVG(可缩放矢量图形)

        SVG可缩放矢量图形(Scalable Vector Graphics)是基于可扩展标记语言(XML),用于描述二维矢量图形的一种图形格式.SVG是W3C("World Wide W ...

  4. 设计模式之Builder

    设计模式总共有23种模式这仅仅是为了一个目的:解耦+解耦+解耦...(高内聚低耦合满足开闭原则) 介绍: Builder模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象. 将一个复杂 ...

  5. Part2-HttpClient官方教程-Chapter2-连接管理

    2.1 连接持久性 建立从一个主机到另一个主机的连接的过程相当复杂,并且涉及两个端点之间的多个分组交换,这可能相当耗时.连接握手的开销可能很大,特别是对于小型的HTTP消息. 如果可以重新使用开放连接 ...

  6. Django-【template】自定义过滤器和自定义标签

      模板语言内置的过滤器和标签比较少,往往会遇到无法满足需求的情况,所以需要我们来自定义.自定义filter和simple_tag在项目中很常用   a.首先检查settings下面INSTALLED ...

  7. 64_f2

    flxmlrpc-0.1.4-5.fc26.x86_64.rpm 22-May-2017 21:32 57950 flxmlrpc-devel-0.1.4-5.fc26.i686.rpm 22-May ...

  8. 【LOJbeta round1】ZQC的手办

    NOI2012-超级钢琴的升级版. 用线段树维护最小值及其出现位置,接下来就跟超级钢琴一个做法了. #include<bits/stdc++.h> #define N 500010 #de ...

  9. node.js2

    同步是指:同步阻塞操作,异步是指:异步非阻塞操作. 第一部分:fs模块 1.引入fs模块 require('fs'); 2.写文件 01.异步写:writeFile fs.writeFile(path ...

  10. Tomcat debug模式下特别慢但是run正常处理方法

    转载自:http://blog.csdn.net/builderwfy/article/details/50785749 到网上查资料发现这是由eclipse和tomcat交互时,在debug模式启动 ...