1. 程式人生 > 其它 >異象石

異象石

給定一個支援增加和刪除的點集,求將點集聯通的邊集的最小值

引理: 將點按照dfn環排列後 求相鄰兩點的距離和就是答案的二倍
嘗試證明:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
using namespace std;

const int N=1e5+10;
typedef long long ll;
int read()
{
	int x=0,f=0,c=getchar();
	while(c<'0'||c>'9'){if(c=='-') f=1;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	return f?-x:x;
}

struct Edge
{
	int to,next,w;
}e[N*2];
int head[N],cnt;
void _add(int a,int b,int c){ e[++cnt]=(Edge){b,head[a],c}; head[a]=cnt;}
void add(int a,int b,int c){ _add(a,b,c); _add(b,a,c);}

int sz[N],top[N],fa[N],son[N],dfn[N];
ll dep[N];
int tim;
void dfs1(int x)
{
	sz[x]=1; dfn[x]=++tim;
	for(int i=head[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if(y==fa[x]) continue;
		dep[y]=dep[x]+e[i].w; fa[y]=x; 
		dfs1(y);
		sz[x]+=sz[y];
		if(sz[son[x]]<sz[y]) son[x]=y;
	}
}

void dfs2(int x,int tp)
{
	top[x]=tp;
	if(son[x]) dfs2(son[x],tp);
	for(int i=head[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if(y==fa[x]||y==son[x]) continue;
		dfs2(y,y);
	}
}

struct Node{ int id,tim;};
bool operator<( const Node &a,const Node &b){ return a.tim<b.tim;}
set< Node > s;
typedef set<Node>::iterator It;

int LCA(int x,int y)
{
	while(top[x]!=top[y])
		dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]];
	return dep[x]<dep[y]?x:y;
}
ll getdis(int x,int y) { return dep[x]+dep[y]-2*dep[LCA(x,y)];}

ll upd(int x)
{
	if(s.size()==1) return 0;
	It it=s.find( (Node){x,dfn[x]} ); It tmp=it; It pre,nxt;
	if(tmp==s.begin()) pre=--s.end(),nxt=++tmp;
	else if(tmp==--s.end()) pre=--tmp,nxt=s.begin();
	else pre=--tmp,tmp++,nxt=++tmp;
	return getdis(pre->id,it->id)+getdis(it->id,nxt->id)-getdis(pre->id,nxt->id);
}

int n,m;
ll ans;
int main()
{
	n=read(); 
	for(int i=1;i<n;i++)
	{
		int x=read(),y=read(),z=read();
		add(x,y,z);
	}
	m=read();
	dfs1(1);  dfs2(1,1);
	while(m--)
	{
		char c=getchar();
		if(c=='?') printf("%lld\n",ans>>1),getchar();
		else
		{
			int x=read();
			if(c=='+') 
			{
				s.insert( (Node){x,dfn[x]} );
				ans=ans+upd(x);
			}
			else ans=ans-upd(x),s.erase( (Node){x,dfn[x]} );
		}
	}
	return 0;
}