MnZn 求助月赛 F 题
查看原帖
MnZn 求助月赛 F 题
324666
diqiuyi奶龙楼主2024/3/9 19:11

rt,TLE on test 1。做法是考虑倒着做,然后维护每棵树的直径的两端,使用树上启发式合并,然后用倍增维护树上两点距离

#include <bits/stdc++.h>
#define fs first
#define sc second
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+(ch&15);
	return f*x;
}
int t,n,rt[100005],q,u,v,w,siz[100005],op[100005],tim[100005],dep[100005],f[100005][18];
long long dis[100005],res[100005],ans;
pair<int,pair<int,int> > e[100005];
vector<pair<int,int> > g[100005];
pair<int,int> zj[100005];
inline int lca(int x,int y){
	if(dep[x]<dep[y]) swap(x,y);
	while(dep[x]>dep[y]) x=f[x][(int)__lg(dep[x]-dep[y])];
	if(x==y) return x;
	for(int i=__lg(dep[x]);~i;i--)
		if(f[x][i]^f[y][i])
			x=f[x][i],y=f[y][i];
	return f[x][0];
}
inline long long gdis(int x,int y){
	int lc=lca(x,y);
	return dis[x]+dis[y]-(dis[lc]<<1);
}
void dfs(int x,int fa,int root){
	rt[x]=root,f[x][0]=fa,dep[x]=dep[fa]+1;
	for(int i=1;i<=__lg(dep[x]);i++)	
		f[x][i]=f[f[x][i-1]][i-1];
	for(int i=0;i<g[x].size();i++)
		if(g[x][i].fs^fa)
			dis[g[x][i].fs]=dis[x]+g[x][i].sc,dfs(g[x][i].fs,x,root);
}
inline void merge(int x){
	int u=e[x].fs,v=e[x].sc.fs,w=e[x].second.second;
	if(siz[rt[u]]<siz[rt[v]]) swap(u,v);
	long long dis1=gdis(u,zj[rt[u]].fs),v1=zj[rt[u]].fs,dis2=gdis(v,zj[rt[v]].fs),v2=zj[rt[v]].fs,dis3,dis4,dis5;
	g[u].push_back(e[x].sc),g[v].push_back(make_pair(e[x].fs,e[x].sc.sc));	
	dis3=gdis(u,zj[rt[u]].second);
	if(dis3>dis1) dis1=dis3,v1=zj[rt[u]].sc;
	dis3=gdis(v,zj[rt[v]].sc);
	if(dis3>dis2) dis2=dis3,v2=zj[rt[v]].sc;
	dis4=gdis(zj[rt[u]].fs,zj[rt[u]].sc);
	dis5=gdis(zj[rt[v]].fs,zj[rt[v]].sc);
	dis3=dis1+dis2+w;
	if(dis3>=dis4&&dis3>=dis5) zj[rt[u]]=make_pair(v1,v2);
	else if(dis4>=dis3&&dis4>=dis5);
	else zj[rt[u]]=zj[rt[v]];
	siz[rt[u]]+=siz[rt[v]],siz[rt[v]]=0;
//	cerr<<x<<endl;
	dis[v]=dis[u]+w,dfs(v,u,rt[u]);
	ans=max(ans,max(dis3,max(dis4,dis5)));
}
signed main(){
	t=read();
	while(t--){
		n=read(),q=read(),ans=0;
		for(int i=1;i<n;i++) tim[i]=q+1,u=read(),v=read(),w=read(),e[i]=make_pair(u,make_pair(v,w));
//		puts("-1");
		for(int i=1;i<=q;i++)
			op[i]=read(),tim[op[i]]=i;
		for(int i=1;i<=n;i++) siz[i]=1,rt[i]=i,zj[i]=make_pair(i,i),dep[i]=1,dis[i]=0,f[i][0]=0,g[i].clear();
//		puts("ccf");
		for(int i=1;i<n;i++)
			if(tim[i]==q+1)
				merge(i);
		res[q+1]=ans;
		for(int i=q;i>1;i--)
			merge(op[i]),res[i]=ans;
//		for(int i=1;i<=n;i++)
//			cout<<f[i][0]<<endl;
		for(int i=2;i<=q+1;i++)
			printf("%lld\n",res[i]);
	}
	return 0;
}
2024/3/9 19:11
加载中...