【dfs序】【set】bzoj3991 [Sdoi2015]寻宝游戏

在考试代码的基础上稍微改改就a了……当时为什么不稍微多想想……

插入/删除一个新节点时就把其dfn插入set/从set中删除。

当前的答案就是dfn上相邻的两两节点的距离和,再加上首尾节点的距离。

比较显然?不会证明……

貌似叫“虚树”?

#include<cstdio>
#include<set>
using namespace std;
#define N 100001
typedef long long ll;
set<int>S;
typedef set<int>::iterator ER;
int n,m;
int v[N<<1],first[N],next[N<<1],w[N<<1],en;
void AddEdge(int U,int V,int W)
{
	v[++en]=V;
	w[en]=W;
	next[en]=first[U];
	first[U]=en;
}
int top[N],dep[N],fa[N],siz[N],son[N],dfn[N],Map[N];
ll sumv[N],ans;
bool a[N];
void dfs(int U)
{
	siz[U]=1;
	for(int i=first[U];i;i=next[i])
	  if(v[i]!=fa[U])
	    {
	      fa[v[i]]=U;
	      dep[v[i]]=dep[U]+1;
	      sumv[v[i]]=sumv[U]+(ll)w[i];
	      dfs(v[i]);
	      siz[U]+=siz[v[i]];
	      if(siz[v[i]]>siz[son[U]])
	        son[U]=v[i];
	    }
}
void df2(int U)
{
	dfn[U]=++en;
	Map[en]=U;
	if(son[U])
	  {
	  	top[son[U]]=top[U];
	  	df2(son[U]);
	  }
	for(int i=first[U];i;i=next[i])
	  if(v[i]!=fa[U]&&v[i]!=son[U])
	    {
	      top[v[i]]=v[i];
	      df2(v[i]);
	    }
}
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]];
	  }
	if(dep[U]>dep[V])
	  swap(U,V);
	return U;
}
ll Query(int U,int V)
{
	return sumv[U]+sumv[V]-(sumv[lca(U,V)]<<1);
}
int main()
{
	int x,y,z;
	scanf("%d%d",&n,&m);
	for(int i=1;i<n;++i)
	  {
	  	scanf("%d%d%d",&x,&y,&z);
	  	AddEdge(x,y,z);
	  	AddEdge(y,x,z);
	  }
	en=0;
	top[1]=1;
	dfs(1);
	df2(1);
	for(;m;--m)
	  {
	  	scanf("%d",&x);
	  	a[x]^=1;
	  	if(a[x])
	  	  {
	  	  	S.insert(dfn[x]);
	  	  	ER it=S.end(); --it;
	  	  	ER jt=S.begin();
	  	  	if(S.size()==0||S.size()==1) ans=0;
	  	  	if(S.size()==2)
	  	  	  ans=(Query(Map[*jt],Map[*it])<<1);
	  	  	else if(S.size()>2&&(*jt)==dfn[x])
	  	  	  {
	  	  	  	ans+=Query(Map[*jt],Map[*it]);
	  	  	  	ER kt=jt; ++kt;
	  	  	  	ans+=Query(Map[*jt],Map[*kt]);
	  	  	  	ans-=Query(Map[*kt],Map[*it]);
	  	  	  }
	  	  	else if(S.size()>2&&(*it)==dfn[x])
	  	  	  {
	  	  	  	ans+=Query(Map[*jt],Map[*it]);
	  	  	  	ER kt=it; --kt;
	  	  	  	ans+=Query(Map[*it],Map[*kt]);
	  	  	  	ans-=Query(Map[*kt],Map[*jt]);
	  	  	  }
	  	  	else if(S.size()>2)
	  	  	  {
	  	  	  	ER kt=S.find(dfn[x]);
	  	  	  	ER lt=kt; --lt;
	  	  	  	ER mt=kt; ++mt;
	  	  	  	ans+=Query(Map[*lt],Map[*kt]);
	  	  	  	ans+=Query(Map[*kt],Map[*mt]);
	  	  	  	ans-=Query(Map[*lt],Map[*mt]);
	  	  	  }
	  	  }
	  	else
	  	  {
	  	  	ER it=S.end(); --it;
	  	  	ER jt=S.begin();
	  	  	if(S.size()==0||S.size()==1) ans=0;
	  	  	if(S.size()==2)
	  	  	  ans=(Query(Map[*jt],Map[*it])<<1);
	  	  	else if(S.size()>2&&(*jt)==dfn[x])
	  	  	  {
	  	  	  	ans-=Query(Map[*jt],Map[*it]);
	  	  	  	ER kt=jt; ++kt;
	  	  	  	ans-=Query(Map[*jt],Map[*kt]);
	  	  	  	ans+=Query(Map[*kt],Map[*it]);
	  	  	  }
	  	  	else if(S.size()>2&&(*it)==dfn[x])
	  	  	  {
	  	  	  	ans-=Query(Map[*jt],Map[*it]);
	  	  	  	ER kt=it; --kt;
	  	  	  	ans-=Query(Map[*it],Map[*kt]);
	  	  	  	ans+=Query(Map[*kt],Map[*jt]);
	  	  	  }
	  	  	else if(S.size()>2)
	  	  	  {
	  	  	  	ER kt=S.find(dfn[x]);
	  	  	  	ER lt=kt; --lt;
	  	  	  	ER mt=kt; ++mt;
	  	  	  	ans-=Query(Map[*lt],Map[*kt]);
	  	  	  	ans-=Query(Map[*kt],Map[*mt]);
	  	  	  	ans+=Query(Map[*lt],Map[*mt]);
	  	  	  }
	  	  	S.erase(dfn[x]);
	  	  }
	  	printf("%lld
",ans);
	  }
	return 0;
}
原文地址:https://www.cnblogs.com/autsky-jadek/p/4429009.html