ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P3320 [SDOI2015]寻宝游戏 题解

2022-05-20 12:34:37  阅读:141  来源: 互联网

标签:pre nxt dist P3320 int 题解 sum Node SDOI2015


题面

需要动态维护一个点集的极小联通子图边权和。可以发现,将点集 \(\{a_i\}\) 中的点按照 dfs 序从小到大排序之后,\(dist(a_1,a_2)+dist(a_2,a_3)+\ldots+dist(a_{k-1},a_k)+dist(a_k,a_1)\) 恰好等于我们要维护的那个边权和的两倍。所以就开一个 set,在加入和删除的时候加上或删去 prenxt 的贡献即可。

点击查看代码
const int N=1e5+13;
struct Edge{int v,w,nxt;}e[N<<1];
int n,m,h[N],tot;
ll dis[N];
inline void add_edge(int u,int v,int w){e[++tot]=(Edge){v,w,h[u]};h[u]=tot;}
int fa[N],dep[N],siz[N],son[N],top[N],id[N],dfs_clock;
void dfs1(int u,int f,int deep){
	dep[u]=deep,fa[u]=f,siz[u]=1;
	int maxson=0;
	for(int i=h[u];i;i=e[i].nxt){
		int v=e[i].v;if(v==f) continue;
		dis[v]=dis[u]+e[i].w;
		dfs1(v,u,deep+1);
		siz[u]+=siz[v];
		if(siz[v]>maxson) maxson=siz[v],son[u]=v;
	}
}
void dfs2(int u,int topf){
	top[u]=topf,id[u]=++dfs_clock;
	if(!son[u]) return;
	dfs2(son[u],topf);
	for(int i=h[u];i;i=e[i].nxt){
		int v=e[i].v;
		if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
	}
}
inline int lca(int u,int v){
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		u=fa[top[u]];
	}
	return id[u]<id[v]?u:v;
}
inline ll dist(int u,int v){return dis[u]+dis[v]-2*dis[lca(u,v)];}
struct Node{
	int x;
	bool operator <(const Node &a)const{return id[x]<id[a.x];}
};
std::set<Node> t;
std::set<Node>::iterator it;
int main(){
//file();
	read(n),read(m);
	for(int i=1;i<n;++i){
		int u,v,w;read(u),read(v),read(w);
		add_edge(u,v,w),add_edge(v,u,w);
	}
	dfs1(1,0,0),dfs2(1,1);
	ll sum=0;
	while(m--){
		int x;read(x);
		if(t.find((Node){x})!=t.end()){//remove
			it=t.find((Node){x});
			int pre=0,nxt=0;
			if(it!=t.begin()) pre=(--it)->x,it=t.find((Node){x});
			if((++it)!=t.end()) nxt=it->x;
			if(pre) sum-=dist(pre,x);if(nxt) sum-=dist(nxt,x);if(pre&&nxt) sum+=dist(pre,nxt);
			t.erase((Node){x});
		}
		else{//insert
			t.insert((Node){x});
			it=t.find((Node){x});
			int pre=0,nxt=0;
			if(it!=t.begin()) pre=(--it)->x,it=t.find((Node){x});
			if((++it)!=t.end()) nxt=it->x;
			if(pre) sum+=dist(pre,x);if(nxt) sum+=dist(nxt,x);if(pre&&nxt) sum-=dist(pre,nxt);
		}
		it=t.end();--it;
		if(it!=t.begin()){
			int u=it->x;it=t.begin();int v=it->x;
			println(sum+dist(u,v));
		}
		else println(sum);
	}
	return 0;
}

标签:pre,nxt,dist,P3320,int,题解,sum,Node,SDOI2015
来源: https://www.cnblogs.com/winterfrost/p/p3320-solution.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有