1. 程式人生 > >loj#2553. 「CTSC2018」暴力寫掛(邊分治+線段樹合併)

loj#2553. 「CTSC2018」暴力寫掛(邊分治+線段樹合併)

傳送門

題解: 按照套路,變成求d1(x,y)+dx+dy2dlca(x,y)d_1(x,y)+d_x+d_y-2*d'lca'(x,y)然後除個二。

在第二棵樹裡面做,相當於支援一下不同子樹內部點距離的最大值。

可以邊分治,然後就跟線段樹結構一樣了,合併成了O(nlogn)O(n \log n),程式碼是真的好寫。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef
pair <int,LL> pii; const int RLEN=1<<18|1; inline char nc() { static char ibuf[RLEN],*ib,*ob; (ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin)); return (ib==ob) ? -1 : *ib++; } inline int rd() { char ch=nc(); int i=0,f=1; while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();} while
(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();} return i*f; } const int N=8e5; const LL INF=1e17; int n,tot,cnt,total,mx,stx,sty,stl; LL dep[N],ans=-INF; int bl[N],sze[N],vs; int rt[N],lc[N*20],rc[N*20],*pos[N]; LL lmax[N*20],rmax[N*20]; vector <pii> e1[N]; vector <pii> e2[N]
; vector <pii> e3[N]; inline void add(vector <pii> *e,int x,int y,int w) {e[x].push_back(pii(y,w)); e[y].push_back(pii(x,w));} inline void dfs1(int x,int f,LL dp) { dep[x]=dp; vector <pii> vec; for(auto v:e1[x]) if(v.first^f) dfs1(v.first,x,dp+v.second), vec.push_back(v); for(int j=0;j<vec.size();++j) { ++tot; add(e2,tot,vec[j].first,vec[j].second); if(j) add(e2,tot,tot-1,0); else add(e2,x,tot,0); } } inline void calcG(int x,int f) { sze[x]=1; for(auto v:e2[x]) if(v.first^f && bl[x]==bl[v.first]) { calcG(v.first,x), sze[x]+=sze[v.first]; int mx_son=max(sze[v.first],total-sze[v.first]); if(mx>=mx_son) mx=mx_son, stx=x, sty=v.first, stl=v.second; } } inline void dfs2(int x,int f,LL dp,int tar) { sze[x]=1; if(x<=n) { *pos[x]=++cnt; (tar ? rmax[*pos[x]] : lmax[*pos[x]])=dp+dep[x]; (tar ? lmax[*pos[x]] : rmax[*pos[x]])=-INF; pos[x]=&(tar ? rc[*pos[x]] : lc[*pos[x]]); } for(auto v:e2[x]) if(v.first^f && bl[v.first]==bl[x]) { dfs2(v.first,x,dp+v.second,tar); sze[x]+=sze[v.first]; } bl[x]=vs; } inline void solve(int x,int y) { ++vs; dfs2(x,y,0,0); ++vs; dfs2(y,x,stl,1); if(sze[x]>1) { total=mx=sze[x]; calcG(x,y); solve(stx,sty); } if(sze[y]>1) { total=mx=sze[y]; calcG(y,x); solve(stx,sty); } } LL base; inline int merge(int x,int y) { if(!x || !y) return x+y; ans=max(ans,lmax[x]+rmax[y]+base); ans=max(ans,lmax[y]+rmax[x]+base); lmax[x]=max(lmax[x],lmax[y]); rmax[x]=max(rmax[x],rmax[y]); lc[x]=merge(lc[x],lc[y]); rc[x]=merge(rc[x],rc[y]); return x; } inline void dfs3(int x,int f,LL dp) { ans=max(ans,2*dep[x]-2*dp); for(auto v:e3[x]) if(v.first^f) { dfs3(v.first,x,dp+v.second); base=-2*dp; rt[x]=merge(rt[x],rt[v.first]); } } int main() { n=rd(); tot=n; for(int i=1;i<n;i++) { int x=rd(), y=rd(), w=rd(); add(e1,x,y,w); } dfs1(1,0,0); for(int i=1;i<=n;i++) pos[i]=&rt[i]; total=mx=tot; calcG(1,0); solve(stx,sty); for(int i=1;i<n;i++) { int x=rd(), y=rd(), w=rd(); add(e3,x,y,w); } dfs3(1,0,0); cout<<ans/2<<'\n'; }