LOJ#2553. 「CTSC2018」暴力写挂(边分治+线段树合并)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35649707/article/details/82944203

传送门

题解:
按照套路,变成求 d 1 ( x , y ) + d x + d y 2 d l c a ( x , y ) d_1(x,y)+d_x+d_y-2*d'lca'(x,y) 然后除个二。

在第二棵树里面做,相当于支持一下不同子树内部点距离的最大值。

可以边分治,然后就跟线段树结构一样了,合并成了 O ( n log n ) 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';
}

猜你喜欢

转载自blog.csdn.net/qq_35649707/article/details/82944203