【CTSC2018】暴力写挂【边分治】【虚树】

题意:给两棵基于同一点集的带边权树,记 lca⁡(x,y),depth⁡(x)\operatorname{lca}(x,y),\operatorname{depth}(x)lca(x,y),depth(x) 为第一棵树上的 lca、到根的边长度之和,lca⁡′(x,y),depth⁡′(x)\operatorname{lca}'(x,y),\operatorname{depth}'(x)lca(x,y),depth(x) 为第二棵树的,最大化

depth⁡(x)+depth⁡(y)−(depth(lca⁡(x,y))⁡+depth⁡′(lca⁡′(x,y)))\operatorname{depth}(x)+\operatorname{depth}(y)-(\operatorname{depth(\operatorname{lca}(x,y))}+\operatorname{depth}'(\operatorname{lca}'(x,y)))depth(x)+depth(y)(depth(lca(x,y))+depth(lca(x,y)))

n≤366666n\leq 366666n366666

这个式子非常诡异,先推一下发现等于这个

12(dist⁡(x,y)+depth⁡(x)+depth⁡(y)−depth⁡′(lca⁡′(x,y)))\frac 12(\operatorname{dist}(x,y)+\operatorname{depth}(x)+\operatorname{depth}(y)-\operatorname{depth}'(\operatorname{lca}'(x,y)))21(dist(x,y)+depth(x)+depth(y)depth(lca(x,y)))

左边是个距离,而右边只有一个二元函数,考虑对第一棵树分治

我们用点分治或边分治可以把 dist⁡(x,y)\operatorname{dist}(x,y)dist(x,y) 拆成两项分别只与 xxxyyy 有关的东西,就可以和 depth⁡\operatorname{depth}depth 合并。现在的问题时怎么处理右边的东西。

不管是点分治还是边分治,每次计算时都有两个点集 S,TS,TS,T,要统计所有 x∈S,y∈Tx\in S,y\in TxS,yT 的贡献。

考虑虚树。在第二棵树上用之前的代价标记 S,TS,TS,T 中的点,然后建出虚树,维护子树内两种集合中的权值最大值,在 lca⁡\operatorname{lca}lca 处统计贡献。

这样复杂度是 O(Slog⁡S)\Omicron(S\log S)O(SlogS),其中 SSS 为两个集合的点集大小。所以只能边分治。

用欧拉序做 O(nlog⁡n)−O(1)\Omicron(n\log n)-\Omicron(1)O(nlogn)O(1) lca⁡\operatorname{lca}lca,总复杂度可以做到严格 O(nlog⁡n)\Omicron(n\log n)O(nlogn)

码量虽大但没什么细节,还是比较好写的。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <vector>
#include <algorithm>
#define MAXN 1000005
#define MAXM 2000005
using namespace std;
typedef long long ll;
const ll INF=1e18;
inline int read()
{int ans=0,f=1;char c=getchar();while (!isdigit(c)) (c=='-')&&(f=-1),c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return f*ans;
}
struct edge{int u,v,w;}e[MAXM];
int head[MAXN],nxt[MAXM],cnt=1;
inline void addnode(int u,int v,int w)
{e[++cnt]=(edge){u,v,w};nxt[cnt]=head[u];head[u]=cnt;
}
vector<edge> E[MAXN];
ll dis[MAXN];
int vis[MAXM],n,tot;
void dfs(int u)
{vis[u]=1;if ((int)E[u].size()<=3){for (int i=0;i<(int)E[u].size();i++){int v=E[u][i].v,w=E[u][i].w;if (vis[v]) continue;dfs(v),addnode(u,v,w),addnode(v,u,w);}return;		}int cur[2]={++tot,++tot},pos=0;addnode(u,cur[0],0),addnode(cur[0],u,0);addnode(u,cur[1],0),addnode(cur[1],u,0);for (int i=0;i<(int)E[u].size();i++){int v=E[u][i].v,w=E[u][i].w;if (vis[v]) continue;E[cur[pos]].push_back((edge){cur[pos],v,w}),pos^=1;}dfs(cur[0]),dfs(cur[1]);
}
void dfs(int u,int f)
{for (int i=head[u];i;i=nxt[i])if (e[i].v!=f)dis[e[i].v]=dis[u]+e[i].w,dfs(e[i].v,u);
}
int rt,siz[MAXN];
ll mn;
void findrt(int u,int f,int sum)
{siz[u]=1;for (int i=head[u];i;i=nxt[i])if (!vis[i>>1]&&e[i].v!=f){findrt(e[i].v,u,sum);if (max(siz[e[i].v],sum-siz[e[i].v])<mn)mn=max(siz[e[i].v],sum-siz[e[i].v]),rt=i;siz[u]+=siz[e[i].v];}
}
namespace VT
{edge e[MAXM];int head[MAXN],nxt[MAXM],cnt;inline void addnode(int u,int v,int w){e[++cnt]=(edge){u,v,w};nxt[cnt]=head[u];head[u]=cnt;}int dfn[MAXN],lis[MAXM],LOG[MAXM],st[MAXM][21],tim;ll dis[MAXN];inline bool cmp(const int& x,const int& y){return dfn[x]<dfn[y];}void dfs(int u,int f){lis[dfn[u]=++tim]=u;for (int i=head[u];i;i=nxt[i])if (e[i].v!=f){	dis[e[i].v]=dis[u]+e[i].w;dfs(e[i].v,u);lis[++tim]=u;}}inline int lca(int x,int y){x=dfn[x],y=dfn[y];if (x>y) swap(x,y);int t=LOG[y-x+1];return min(st[x][t],st[y-(1<<t)+1][t],cmp);}void input(){LOG[0]=-1;for (int i=1;i<MAXM;i++) LOG[i]=LOG[i>>1]+1;for (int i=1;i<n;i++){int u,v,w;u=read(),v=read(),w=read();addnode(u,v,w),addnode(v,u,w);} dfs(1,0);for (int i=1;i<=tim;i++) st[i][0]=lis[i];for (int j=1;j<21;j++)for (int i=1;i+(1<<(j-1))<=tim;i++)st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1],cmp);}vector<int> s,son[MAXN];ll val[MAXN],x[MAXN],y[MAXN],ans;int type[MAXN];inline void insert(int u,ll v,int t){val[u]=v,type[u]=t,s.push_back(u);}void dfs(int u){x[u]=y[u]=-INF;if (type[u]==1) x[u]=val[u];if (type[u]==2) y[u]=val[u];for (int i=0;i<(int)son[u].size();i++){dfs(son[u][i]);ans=max(ans,max(x[u]+y[son[u][i]],x[son[u][i]]+y[u])-2*dis[u]);x[u]=max(x[u],x[son[u][i]]),y[u]=max(y[u],y[son[u][i]]);}}int stk[MAXN],tp;ll solve(){sort(s.begin(),s.end(),cmp);int siz=s.size();for (int i=0;i<siz-1;i++) s.push_back(lca(s[i],s[i+1]));sort(s.begin(),s.end(),cmp);s.erase(unique(s.begin(),s.end()),s.end());tp=0;for (int i=0;i<(int)s.size();i++){while (tp&&lca(stk[tp],s[i])!=stk[tp]) --tp;if (tp) son[stk[tp]].push_back(s[i]);stk[++tp]=s[i];}ans=-INF;dfs(stk[1]);for (int i=0;i<(int)s.size();i++) son[s[i]].clear();s.clear();return ans;}
}
void dfs(int u,int f,ll d,int type)
{if (u<=n) VT::insert(u,dis[u]+d,type);for (int i=head[u];i;i=nxt[i])if (!vis[i>>1]&&e[i].v!=f)dfs(e[i].v,u,d+e[i].w,type);
}
ll ans=-INF;
void solve(int sum)
{if (mn==INF) return;vis[rt>>1]=1;dfs(e[rt].v,0,0,1);dfs(e[rt].u,0,0,2);ans=max(ans,VT::solve()+e[rt].w);int sz=siz[e[rt].v],cur=rt;mn=INF,findrt(e[cur].v,0,sz),solve(sz);mn=INF,findrt(e[cur].u,0,sum-sz),solve(sum-sz);
}
int main()
{tot=n=read();for (int i=1;i<n;i++){int u,v,w;u=read(),v=read(),w=read();E[u].push_back((edge){u,v,w}),E[v].push_back((edge){v,u,w});}VT::input();dfs(1);dfs(1,0);memset(vis,0,sizeof(vis));mn=INF,findrt(1,0,tot),solve(tot);for (int i=1;i<=n;i++) ans=max(ans,2*(dis[i]-VT::dis[i]));cerr<<ans<<'\n';cout<<(ans>>1);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/314837.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

hdu 6153 A Secret kmp + dp

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你两个串a,ba,ba,b&#xff0c;让你求对于bbb的每个后缀&#xff0c;设其长度为lenlenlen&#xff0c;其在aaa中出现的次数为cntcntcnt&#xff0c;那么他的贡献为len∗cntlen*cntlen∗cnt&#xff0c;求每…

中国程序员,请挺起你的腰杆!

这两天发生一个事&#xff0c;登月50周年之际&#xff0c;阿波罗11号制导计算机&#xff08;AGC&#xff09;指令和登月模块的源代码在Github上发布公开了&#xff0c;大量中国人前往围观&#xff0c;把issues区当成了论坛版块灌水留言。猎奇起哄本为消遣作乐&#xff0c;有不妥…

【BZOJ3252】攻略【闵可夫斯基和】【堆启发式合并】

题意&#xff1a;给一棵 nnn 个点的有点权的树&#xff0c;你需要找 kkk 条根到叶子的路径&#xff0c;使得路径并集的权值和最大。 n≤2105n\leq 2\times 10^5n≤2105 其实就是个贪心&#xff0c;只是从这个角度更自然一点( 先有个显然的 dp&#xff0c;设 f(u,k)f(u,k)f(u,…

Codeforces Round #592 (Div. 2) G. Running in Pairs 构造(水)

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 史上最水GGG题&#xff0c;没有之一。 考虑最小的情况如何构造&#xff0c;显然就是让a,ba,ba,b都1−n1-n1−n依次排列即可&#xff0c;这样的最小值为n∗(n1)2\frac{n*(n1)}{2}2n∗(n1)​…

Async,Await和ConfigureAwait的关系

在.NET Framework 4.5中&#xff0c;async / await关键字已添加到该版本中&#xff0c;简化多线程操作&#xff0c;以使异步编程更易于使用。为了最大化利用资源而不挂起UI&#xff0c;你应该尽可能地尝试使用异步编程。虽然async / await让异步编程更简单&#xff0c;但是有一…

【洛谷P5114】八月脸【边分治】【闵可夫斯基和】

题意&#xff1a;一棵 nnn 个点的树&#xff0c;每个点有两个权值 ai,bia_i,b_iai​,bi​&#xff0c;有黑白两种颜色。mmm 次询问&#xff0c;每次给定一个 kkk,求一条端点异色的路径&#xff0c;使得 k∑ai∑bik\sum a_i\sum b_ik∑ai​∑bi​ 最大化。 n≤2105n\leq 2\times…

Educational Codeforces Round 75 (Rated for Div. 2) E2. Voting (Hard Version) 贪心

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; n≤2e5,m≤n,p≤1e9n\le2e5,m\le n,p\le 1e9n≤2e5,m≤n,p≤1e9 思路&#xff1a; 首先需要发现一些性质&#xff0c;假设preipre_iprei​代表所有mj<im_j< imj​<i的pjp_jpj​和。可以发现&#…

【招聘(深圳)】敢为软件技术有限公司 .Net 工程师

敢为软件介绍&#xff1a;深圳市敢为软件技术有限公司致力于打造面向未来的最酷最具影响力的高科技公司。敢为软件在万物互联、行业应用、大屏可视化及自然交互等方面形成完整的闭环&#xff0c;是物联网领域连接能力最强、应用领域最广、用户体验最好的高科技公司。在万物互联…

【WC2018】通道【边分治】【虚树】【树的直径】

题意&#xff1a;给三棵基于同一点集的带边权的树&#xff0c;边权非负&#xff0c;求两点间三棵树上距离之和的最大值。 n≤105n\leq 10^5n≤105 一句话题解&#xff1a;在第一棵树上做边分治&#xff0c;丢到第二棵树上建虚树&#xff0c;在虚树上根据第三棵树的直径dp。 首…

DevOps案例研究:知人善任——Google敏捷核心文化

内容来源&#xff1a;DevOps案例深度研究-Google敏捷实践战队&#xff0c;本文只展示部分PPT及研究成果&#xff0c;更多细节请关注案例分享会。本文内容贡献者&#xff1a;陈霁、刘翀、谈佳婧、张霖。阅读干货前先感受一下热烈的氛围~一、Google如何快速交付原型1.1 Savioke公…

Educational Codeforces Round 111 (Rated for Div. 2) E. Stringforces 二分 + 状压dp

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你一个串&#xff0c;只包含前kkk个字母和&#xff1f;&#xff1f;&#xff1f;&#xff0c;定义fif_ifi​表示第iii个字母在串中出现的最长连续长度&#xff0c;你现在需要将???替换为前kkk个字母&am…

MTT 学习笔记

很久以前就听说了这东西&#xff0c;一直没空学。最近重学多项式&#xff0c;就重新搞了一下。 MTT 主要解决的是任意模数&#xff08;或者说是没有模数&#xff09;的多项式乘法&#xff0c;可以用于应对专门恶心人的毒瘤题。 首先&#xff0c;假设多项式次数 10510^5105,值…

在 VS Code 中轻松 review GitHub Pull Requests

相信大家在平时工作或者自己的项目中&#xff0c;一定都有在 GitHub 上进行 Code Review 的经历。对于韩老师来说&#xff0c;不论是平时工作的项目&#xff0c;还是自己的业余项目&#xff0c;代码基本都是在 GitHub 上。所以&#xff0c;在 GitHub 上进行 Pull Requests 的 C…

Codeforces Round #732 (Div. 2) C. AquaMoon and Strange Sort 思维

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你nnn个数&#xff0c;每个数初始方向是向右&#xff0c;每次可以交换相邻两个位置并且将这两个位置的方向调换&#xff0c;问这个序列的最终状态能否是非递减且方向都向右。 n≤1e5,ai≤1e5n\le1e5,a_i\l…

【CC November Challenge 2012】Arithmetic Progressions【分块】【FFT】

题意&#xff1a;给定长度为 nnn 的正整数序列 AAA,求满足 i<j<k,Aj−AiAk−Aji<j<k,A_j-A_iA_k-A_ji<j<k,Aj​−Ai​Ak​−Aj​ 的三元组个数。 n≤105,Ai≤3104n\leq 10^5,A_i\leq 3\times 10^4n≤105,Ai​≤3104 三个位置只有 jjj 限制比较紧&#xff0c…

火热的云原生到底是什么?一文了解云原生四要素!

所谓云原生&#xff0c;它不是一个产品&#xff0c;而是一套技术体系和一套方法论&#xff0c;而数字化转型是思想先行&#xff0c;从内到外的整体变革。更确切地说&#xff0c;它是一种文化&#xff0c;更是一种潮流&#xff0c;是云计算的一个必然导向。随着虚拟化技术的成熟…

Codeforces Round #732 (Div. 2) D. AquaMoon and Chess 组合数学 + 找规律

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你一个010101串&#xff0c;当且仅当某个111的某一边i1,i−1i1,i-1i1,i−1有111&#xff0c;这个111可以跟i2,i−2i2,i-2i2,i−2交换位置&#xff0c;问最终能产生多少状态。 n≤1e5n\le1e5n≤1e5 思路&a…

为什么说拥抱.NET CORE的时候到了

微软和社区已经做了大量艰苦的工作&#xff0c;使.Net Core成为市场上具有竞争力的框架&#xff0c;帮助开发人员快速开发具有最佳性能和可扩展性的强大应用程序。做的最棒的事情是.Net Framework开发人员不需要任何新知识来处理.Net Core。这也是开发人员在很短的时间内采用.N…

【HNOI2016】序列【莫队】【单调栈】【ST表】

题意&#xff1a;给定序列 aia_iai​&#xff0c;qqq 次询问 [l,r][l,r][l,r] 所有子区间最小值之和。 n,q≤105n,q\leq 10^5n,q≤105 这种题一眼看上去是离线线段树&#xff0c;但这题每移动一位要维护区间取 min⁡\minmin&#xff0c;历史值之和&#xff0c;非常不可做。 所…

湖南大学第十六届程序设计竞赛 B Yuki with emofunc and playf 同余最短路

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 初始有一个数111&#xff0c;你每次可以将其∗10*10∗10或者(x−1)(x-1)(x−1)&#xff0c;现在给你xxx&#xff0c;问最少经过多少步能到达nnn。 1≤n≤1e6,1≤m≤1e91\le n\le1e6,1\le m\le1e91≤n≤1e6,1…