题目大意:题目说得很清楚。
题解思路:由于T2生成随机&&修改随机,所以平均每次修改都在log级别!我们考虑对于 T1上的每个点下面再挂一个点,边权为在 T2中的深度。此时两点的距离即为两个节点新挂的节点的距离。由于边权非负,所以我们等价于维护新树上的直径。那么该如何动态维护直径呢?
可以欧拉序上建线段树维护。
前置技能:1.欧拉序 2.线段树
想学如何动态维护树直径的同学我强烈推荐这三篇博客
https://www.cnblogs.com/Mrzdtz220/p/11664538.html
https://zhuanlan.zhihu.com/p/84236967
https://www.cnblogs.com/TinyWong/p/11260601.html
不过单这题而言我的做法并不是正解,出题人似乎是利用了树的某些性质可以省去线段树维护这一操作,不过像我这样比较笨的人就只会用数据结构暴力维护啦。
#include<bits/stdc++.h> //#include<tr1/unordered_map> using namespace std; typedef long long ll; typedef pair<int,int> PII; #define ls l,mid,rt<<1 #define rs mid+1,r,rt<<1|1 #define endl ' ' #define ps puts("###") #define int long long const int MAXN = 4e5+10; const double EPS = 1e-12; const ll mod = 1e9+7; //tr1::unordered_map<int,int>ump; ll Max(ll a,ll b,ll c){ if(a>=b&&a>=c)return a; if(b>=a&&b>=c)return b; return c; } int n,m; int dfn[MAXN],in[MAXN],out[MAXN]; ll dep1[MAXN],dep2[MAXN],dis[MAXN]; ll ans[MAXN<<2],maxL[MAXN<<2],maxR[MAXN<<2],val[MAXN<<2],minv[MAXN<<2]; struct node{ int to; ll cost; }; vector<node>G1[MAXN],G2[MAXN]; void dfs2(int u,int fa){ for(auto v:G2[u]){ if(v.to==fa)continue; dep2[v.to]=dep2[u]+v.cost; dfs2(v.to,u); } } int tot; void dfs3(int u,int fa){ dfn[++tot]=u; in[u]=tot; for(auto v:G1[u]){ if(v.to==fa)continue; dep1[v.to]=dep1[u]+v.cost; dfs3(v.to,u); dfn[++tot]=u; } out[u]=tot; } void Pushup(int rt){ val[rt]=max(val[rt<<1],val[rt<<1|1]); minv[rt]=max(minv[rt<<1],minv[rt<<1|1]); maxL[rt]=Max(maxL[rt<<1],maxL[rt<<1|1],val[rt<<1]+minv[rt<<1|1]); maxR[rt]=Max(maxR[rt<<1],maxR[rt<<1|1],val[rt<<1|1]+minv[rt<<1]); ans[rt]=Max(ans[rt<<1],ans[rt<<1|1],max(maxL[rt<<1]+val[rt<<1|1],maxR[rt<<1|1]+val[rt<<1])); } void Build(int l,int r,int rt){ if(l==r){ val[rt]=dep1[dfn[l]]; minv[rt]=-2*dep1[dfn[l]]; maxL[rt]=maxR[rt]=-dep1[dfn[l]]; ans[rt]=0; return ; } int mid=(l+r)/2; Build(ls); Build(rs); Pushup(rt); } void Update(int l,int r,int rt,int pos,ll c){ if(l==r&&l==pos){ val[rt]+=c; maxL[rt]-=c; maxR[rt]-=c; minv[rt]-=2*c; return ; } int mid=(l+r)/2; if(pos<=mid)Update(ls,pos,c); else Update(rs,pos,c); Pushup(rt); } void dfs4(int u,ll k){ Update(1,tot,1,in[u+200000],k); //Update(1,tot,1,out[u+100000],-k); for(auto v:G2[u]){ if(dep2[v.to]<=dep2[u])continue; dfs4(v.to,k); } } void solve(){ cin>>n>>m; for(int i=1,u,v,w;i<n;i++){ cin>>u>>v>>w; G1[u].push_back(node{v,(ll)w}); G1[v].push_back(node{u,(ll)w}); } for(int i=1,u,v,w;i<n;i++){ cin>>u>>v>>w; G2[u].push_back(node{v,(ll)w}); G2[v].push_back(node{u,(ll)w}); } dep1[1]=dep2[1]=0; dfs2(1,0); for(int i=1;i<=n;i++){ G1[i].push_back(node{200000+i,dep2[i]}); G1[200000+i].push_back(node{i,dep2[i]}); } dfs3(1,0); Build(1,tot,1); cout<<ans[1]<<endl; int x;ll k; while(m--){ cin>>x>>k; dfs4(x,k); cout<<ans[1]<<endl; } } signed main() { ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); int T=1; //scanf("%d",&T); while(T--) solve(); }