LOJ#2339. 「WC2018」通道(邊分治+虛樹)
阿新 • • 發佈:2018-12-14
題解: 考慮兩棵樹怎麼做,要求,把掛在下面,長度為,然後就是。
相當於對於第一棵樹求在第二棵樹裡面的直徑。 因為沒有負邊權,我們直接記錄最長鏈即可。
第三棵樹採用邊分治,對於每一層,相當於求。 用類似的方法,接在下方,然後相當於是第一棵樹的每棵子樹求一下兩類點(邊分治的兩邊)的直徑。 到集合的直徑一定在集合最長鏈,集合最長鏈的兩端取得(在沒有負權的情況下)。 然後就是一樣的做法了。
用歸併排序建虛樹,lca,可以做到。
#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 LL rd() {
char ch=nc(); LL 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=2e5+50, L=18;
int n,lg[N]; LL ans;
struct chain {
int x,y; LL l;
chain(int x=0,int y=0,LL l=0) : x(x),y(y),l(l) {}
friend inline bool operator <(const chain &a,const chain &b) {return a.l<b.l || (a.l==b.l && a.x<b.x);}
};
struct T1 {
int dfn[N],sze[N],pos[N],st[N][L+1],id[N];
LL dep[N]; vector <pii> e[N];
int tot,ind;
inline void dfs(int x,int f) {
id[dfn[x]=++ind]=x; sze[x]=1;
st[pos[x]=++tot][0]=ind;
for(auto v:e[x]) if(v.first^f) {
dep[v.first]=dep[x]+v.second;
dfs(v.first,x); st[++tot][0]=dfn[x];
sze[x]+=sze[v.first];
}
}
inline void init() {
for(int i=1;i<n;i++) {
int x=rd(), y=rd(); LL w=rd();
e[x].push_back(pii(y,w));
e[y].push_back(pii(x,w));
} dfs(1,0);
for(int i=1;i<=lg[tot];i++)
for(int j=1;j+(1<<i)-1<=tot;++j)
st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
}
inline int lca(int x,int y) {
if(pos[x]>pos[y]) swap(x,y);
int l=lg[pos[y]-pos[x]+1];
return id[min(st[pos[x]][l],st[pos[y]-(1<<l)+1][l])];
}
inline bool in(int x,int y) {return dfn[y]<dfn[x]+sze[x] && dfn[y]>dfn[x];}
} t1,t2;
namespace t3 {
int stx,sty,mxv,total; LL stl;
int bl[N],sze[N],vs,tot; LL dep[N];
vector <pii> e1[N];
vector <pii> e2[N];
vector <int> e[N];
inline void dfs(int x,int f) {
vector <pii> vec;
for(auto v:e1[x]) if(v.first^f)
vec.push_back(v), dfs(v.first,x);
for(int j=0;j<vec.size();++j) {
e2[++tot].push_back(vec[j]);
e2[vec[j].first].push_back(pii(tot,vec[j].second));
int pre=j ? tot-1 : x;
e2[pre].push_back(pii(tot,0));
e2[tot].push_back(pii(pre,0));
}
}
inline void init() {
for(int i=1;i<n;i++) {
int x=rd(), y=rd(); LL w=rd();
e1[x].push_back(pii(y,w));
e1[y].push_back(pii(x,w));
} tot=n; dfs(1,0);
}
inline void calcG(int x,int f) {
sze[x]=1;
for(auto v:e2[x]) if(v.first^f && bl[v.first]==bl[x]) {
calcG(v.first,x); sze[x]+=sze[v.first];
if(max(sze[v.first],total-sze[v.first])<=mxv) {
mxv=max(sze[v.first],total-sze[v.first]);
stx=x; sty=v.first; stl=v.second;
}
} bl[x]=vs;
}
int stk[N],id[N],top,ic;
int fa[N],a[N],cnt,rt;
chain mx[N][2];
inline void build_vir(vector <int> &q) {
cnt=top=0;
for(auto i:q) a[++cnt]=i;
for(auto i:q) {
if(!top) stk[++top]=rt=i;
else {
int l=t1.lca(i,stk[top]);
while(t1.in(l,stk[top])) {
if(top==1 || t1.in(stk[top-1],l)) fa[stk[top]]=l;
--top;
}
if(l!=stk[top]) {
if(!top) rt=l;
a[++cnt]=l;
fa[l]=stk[top];
stk[++top]=l;
}
fa[i]=stk[top];
stk[++top]=i;
}
}
for(int i=1;i<=cnt;i++) e[a[i]].clear();
for(int i=1;i<=cnt;i++) if(a[i]!=rt) e[fa[a[i]]].push_back(a[i]);
}
inline LL ask_dis(int x,int y) {
int l=t2.lca(x,y);
return t2.dep[x]+t2.dep[y]-2*t2.dep[l]+t1.dep[x]+dep[x]+t1.dep[y]+dep[y];
}
inline void upt_ans(int i,int x,int y) {
ans=max(ans,ask_dis(x,y)-2*t1.dep[i]);
}
inline chain merge(chain &a,chain &b) {
chain c=chain(0,0,0);
c=max(c,chain(a.x,b.x,ask_dis(a.x,b.x)));
c=max(c,chain(a.x,b.y,ask_dis(a.x,b.y)));
c=max(c,chain(a.y,b.x,ask_dis(a.y,b.x)));
c=max(c,chain(a.y,b.y,ask_dis(a.y,b.y)));
return max(a,max(b,c));
}
inline void merge(int x,int y) {
for(int i=0;i<=1;i++)