[LOJ2553]暴力写挂
锟题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]暴力写挂的更多相关文章
- BZOJ5341[Ctsc2018]暴力写挂——边分治+虚树+树形DP
题目链接: CSTC2018暴力写挂 题目大意:给出n个点结构不同的两棵树,边有边权(有负权边及0边),要求找到一个点对(a,b)满足dep(a)+dep(b)-dep(lca)-dep'(lca)最 ...
- 【CTSC2018】暴力写挂(边分治,虚树)
[CTSC2018]暴力写挂(边分治,虚树) 题面 UOJ BZOJ 洛谷 题解 发现第二棵树上的\(LCA\)的深度这玩意没法搞,那么枚举在第二棵树上的\(LCA\). 然后剩下的部分就是\(dep ...
- [CTSC2018]暴力写挂——边分树合并
[CTSC2018]暴力写挂 题面不错 给定两棵树,两点“距离”定义为:二者深度相加,减去两棵树上的LCA的深度(深度指到根节点的距离) 求最大的距离. 解决多棵树的问题就是降维了. 经典的做法是边分 ...
- [LOJ#2553][CTSC2018]暴力写挂
[LOJ#2553][CTSC2018]暴力写挂 试题描述 temporaryDO 是一个很菜的 OIer .在 4 月,他在省队选拔赛的考场上见到了<林克卡特树>一题,其中 \(k = ...
- BZOJ5341: [Ctsc2018]暴力写挂
BZOJ5341: [Ctsc2018]暴力写挂 https://lydsy.com/JudgeOnline/problem.php?id=5341 分析: 学习边分治. 感觉边分治在多数情况下都能用 ...
- Loj #2553. 「CTSC2018」暴力写挂
Loj #2553. 「CTSC2018」暴力写挂 题目描述 temporaryDO 是一个很菜的 OIer .在 4 月,他在省队选拔赛的考场上见到了<林克卡特树>一题,其中 \(k = ...
- UOJ400/LOJ2553 CTSC2018 暴力写挂 边分治、虚树
传送门--UOJ 传送门--LOJ 跟隔壁通道是一个类型的 要求的式子中有两个LCA,不是很方便,因为事实上在这种题目中LCA一般都是枚举的对象-- 第二棵树上的LCA显然是动不了的,因为没有其他的量 ...
- 并不对劲的bzoj5341:loj2553:uoj400:p4565:[Ctsc2018]暴力写挂
题目大意 有两棵\(n\)(\(n\leq366666\))个节点的树,\(T\)和\(T'\),有边权 \(dep(i)\)表示在\(T\)中\(i\)号点到\(1\)号点的距离,\(dep'(i) ...
- LOJ#2553 暴力写挂
题意:给定两棵树T1,T2,求d1[x] + d1[y] - d1[lca1(x, y)] - d2[lca2(x, y)]的最大值. 解:考虑把上面这个毒瘤东西化一下.发现它就是T1中x,y到根的路 ...
随机推荐
- 【洛谷 P4116】 Qtree3 (树链剖分)
题目链接 树剖练手题,想复习下树剖. 第一次提交\(T\)成QQC 看我 ??? 看了数据范围的确挺恶心的,我的复杂度是\(O(Mlog^2N)\)的,数据范围有三段 For 1/3 of the t ...
- 启动Eclipse时,弹出failed to load the jni shared library
JDK版本和Eclipse版本不同的问题,JDK版本为64位,Eclipse版本为32位.
- CART算法(转)
来源:http://www.cnblogs.com/pinard/p/6053344.html 作者:刘建平Pinard 对于C4.5算法,我们也提到了它的不足,比如模型是用较为复杂的熵来度量,使用了 ...
- sublime3插件安装及报错处理
ctrl+shift+p调用出窗口:输入install package,然后输入想安装的插件. 有些用户安装的可能是国内破解版的,我的就是,然后install package报错: Package C ...
- Linux-进程间通信(N): 各种IPC的使用场景
1. 管道:只能用于具有亲缘关系的进行通信,使用面相对较窄,实际开发中较少使用: 2. FIFO(命名管道):可以用于任意进程间的通信,对于大块数据的传输效率较高,可应用于单进程大量数据传递,和多个进 ...
- gpio子系统和pinctrl子系统(下)
情景分析 打算从两个角度来情景分析,先从bsp驱动工程师的角度,然后是驱动工程师的角度,下面以三星s3c6410 Pinctrl-samsung.c为例看看pinctrl输入参数的初始化过程(最开始的 ...
- 网络知识===《图解TCP/IP》学习笔记——网络的构成要素
首先引入网络构成要素图 图片来自<图解TCP/IP--P37> 1.通信媒介与数据链路 计算机之间通过电缆相互连接,电缆可以分为多种,包括双绞线电缆,光纤电缆,同轴电缆,串行电缆等. 图片 ...
- mac 使用清除废纸篓或彻底删除某文件 附加: smb afp ftp NAS 访问服务器相关
mac 使用清除废纸篓或彻底删除某文件 附加: smb afp ftp NAS 访问服务器相关 mac 下删除文件方法: 1.使用 cleanmymac 使用 cleamymac 的清理 和 逐个 ...
- vue-router 基础
安装 NPM npm install vue-router 如果在一个模块化工程中使用它,必须要通过 Vue.use() 明确地安装路由功能: import Vue from 'vue' import ...
- 4.Python3标准库--算法
(一)functools:管理函数的工具 import functools ''' functools模块提供了一些工具来管理或扩展和其他callable对象,从而不必完全重写 ''' 1.修饰符 f ...