[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到根的路 ...
随机推荐
- 【洛谷 T47488】 D:希望 (点分治)
题目链接 看到这种找树链的题目肯定是想到点分治的. 我码了一下午,\(debug\)一晚上,终于做到只有两个点TLE了. 我的是不完美做法 加上特判\(A\)了这题qwq 记录每个字母在母串中出现的所 ...
- C++中多线程与Singleton的那些事儿
前言 前段时间在网上看到了个的面试题,大概意思是如何在不使用锁和C++11的情况下,用C++实现线程安全的Singleton. 看到这个题目后,第一个想法就是用Scott Meyer在<Effe ...
- JDBC数据源连接池(2)---C3P0
我们接着<JDBC数据源连接池(1)---DBCP>继续介绍数据源连接池. 首先,在Web项目的WebContent--->WEB-INF--->lib文件夹中添加C3P0的j ...
- yii2 一对多关系的对分页造成的影响
下面代码中关联descies时,匹配较多,造成分页数不对,需要加条件限制: $model = User::find() ->joinWith('app') ->joinWith(['des ...
- IE11中实现颜色渐变
background: -ms-linear-gradient(left,#daa23e,#ad7f27); 下面是css3中颜色渐变对各个浏览器的写法:background: -webkit-lin ...
- MiCode108 猜数字
Description 相传,十八世纪的数学家喜欢玩一种猜数字的小游戏,规则如下: 首先裁判选定一个正整数数字 N (2 \leq N \leq 200)N(2≤N≤200),然后选择两个不同的整数X ...
- SPOJ 375
默默一看提交时间 -- 这是我以前的代码风格-- #include <cstdio> #include <cstring> #include <vector> #i ...
- Restful Framework (三)
目录 一.版本 二.解析器 三.序列化 四.请求数据验证 一.版本 回到顶部 程序也来越大时,可能通过版本不同做不同的处理 没用rest_framework之前,我们可以通过以下这样的方式去获取. c ...
- 深入解析当下大热的前后端分离组件django-rest_framework系列四
查漏补缺系列 解析器 request类 django的request类和rest-framework的request类的源码解析 局部视图 from rest_framework.parsers im ...
- 175. Combine Two Tables
Table: Person +-------------+---------+ | Column Name | Type | +-------------+---------+ | PersonId ...