牛客挑战赛45-D题[坐标]
坐标
https://ac.nowcoder.com/acm/contest/8563/D
先将T2的贡献计算出来,然后在T1的对应节点上挂一条边权为dep[i]的边.那么题目就变成了求整棵树的直径.用两遍dfs得出直径的两个端点,然后就得出答案.因为是随机数据,每次暴力更新的点不会很多,暴力更新维护一下端点就行.
下面是官方题解,但是没有代码,加了有注释的代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
const int maxn = 2e5+20;
int n,q,tot;
struct node{
int v,val;
};
vector<node>e1[maxn],e2[maxn];
int f2[maxn],dep2[maxn];
//dfs1 获取T2的dep2
void dfs1(int u,int fa)
{
f2[u]=fa;
for(auto &t:e2[u]){
if(t.v==fa)continue;
dep2[t.v]=dep2[u]+t.val;
dfs1(t.v,u);
}
}
int f1[maxn],siz[maxn],deep[maxn],son[maxn];
int dep1[maxn];
void dfs2(int u,int fa)
{
f1[u]=fa;siz[u]=1;deep[u]=deep[fa]+1;
for(auto &t:e1[u]){
if(t.v==fa)continue;
dep1[t.v]=dep1[u]+t.val;
dfs2(t.v,u);
siz[u]+=siz[t.v];
if(!son[u]||siz[t.v]>siz[son[u]])son[u]=t.v;
}
}
int top[maxn];
void dfs3(int u,int topf)
{
top[u]=topf;
if(!son[u])return ;
dfs3(son[u],topf);
for(auto &t:e1[u]){
if(t.v==son[u]||t.v==f1[u])continue;
dfs3(t.v,t.v);
}
}
bool vis[maxn];
ll dtree,now,S,E,D;
void dfs4(int u,int dval)
{
// cout<<u<<' '<<dval;
vis[u]=true;
if(dval>dtree)dtree=dval,now=u;
for(auto &t:e1[u]){
if(vis[t.v])continue;
dfs4(t.v,dval+t.val);
}
}
int lca(int u,int v)
{
while(top[u]^top[v]){
if(deep[top[u]]<=deep[top[v]])swap(u,v);
u=f1[top[u]];
}
return deep[u]<deep[v]?u:v;
}
ll dis(int u,int v){
return dep1[u]+dep1[v]-2*dep1[lca(u,v)];
}
ll w;
void dfs5(int u,int fa)
//暴力询问当更新当前u点时有没有更改原来的S和E
{
dep1[u+n]+=w;
ll D1=dis(u+n,S),D2=dis(u+n,E);
ll D=max(D1,D2);
if(D1>D2)now=S;else now=E;
if(D>dtree)dtree=D,S=now,E=n+u;
for(auto &t:e2[u]){
if(t.v==fa)continue;
dfs5(t.v,u);
}
}
signed main()
{
cin>>n>>q;
for(int i=1;i<n;i++){
int u,v,w;cin>>u>>v>>w;
// cout<<u<<v<<w<<endl;
e1[u].push_back({v,w});
e1[v].push_back({u,w});
}
for(int i=1;i<n;i++){
int u,v,w;cin>>u>>v>>w;
e2[u].push_back({v,w});
e2[v].push_back({u,w});
}
dfs1(1,0);
//在得到T2的dep之后给T1加一条边
for(int i=1;i<=n;i++){
e1[i].push_back({i+n,dep2[i]});
e1[i+n].push_back({i,dep2[i]});
}
//T1树链剖分
dfs2(1,0);
dfs3(1,1);
//dfs两遍求树的直径
dfs4(1,0);S=now;
dtree=0;memset(vis,0,sizeof vis);
dfs4(S,0);E=now;
cout<<dtree<<endl;
for(int i=1;i<=q;i++){
int u;cin>>u>>w;
//暴力更新
dfs5(u,f2[u]);
cout<<dtree<<endl;
}
return 0;
}
