1. 程式人生 > 實用技巧 >牛客挑戰賽45 D.座標

牛客挑戰賽45 D.座標

題目連結

題目大意:題目說得很清楚。

題解思路:由於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 '\n'
#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(); }