LOJ #6145. 「2017 山东三轮集训 Day7」Easy 点分树+线段树

这个就比较简单了~

Code: 

#include <cstdio> 
#include <algorithm>  
#define N 100004 
#define inf 1000000000   
#define setIO(s) freopen(s".in","r",stdin)  //    , freopen(s".out","w",stdout)          
using namespace std;  
int n,edges; 
int hd[N],to[N<<1],nex[N<<1],val[N<<1]; 
void add(int u,int v,int c)
{
	nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c; 
} 
namespace tree
{ 
	int size[N],son[N],dep[N],dis[N],fa[N],top[N];
	void dfs1(int u,int ff)
	{ 
		size[u]=1,fa[u]=ff; 
		for(int i=hd[u];i;i=nex[i]) 
			if(to[i]!=ff)
			{
				dis[to[i]]=dis[u]+val[i],dep[to[i]]=dep[u]+1; 
				dfs1(to[i],u),size[u]+=size[to[i]]; 
				if(size[to[i]]>size[son[u]]) son[u]=to[i];           
			}
	} 
	void dfs2(int u,int tp)
	{
		top[u]=tp; 
		if(son[u]) dfs2(son[u],tp); 
		for(int i=hd[u];i;i=nex[i]) 
			if(to[i]!=fa[u]&&to[i]!=son[u]) 
				dfs2(to[i],to[i]); 
	} 
	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; 
	}
	int Dis(int x,int y)
	{
		return dis[x]+dis[y]-(dis[LCA(x,y)]<<1); 
	} 
}; 
namespace seg 
{ 
	int tot;                         
	#define lson t[x].ls 
	#define rson t[x].rs
	struct Node 
	{
		int ls,rs,min; 
	}t[N*100];  
	int newnode() 
	{
		t[++tot].min=inf;           
		return tot;    
	}    
	void pushup(int x) 
	{ 
		t[x].min=inf; 
		if(lson) t[x].min=min(t[x].min,t[lson].min); 
		if(rson) t[x].min=min(t[x].min,t[rson].min);    
	}
	void update(int &x,int l,int r,int p,int v) 
	{
		if(!x) x=newnode();    
		if(l==r) 
		{ 
			t[x].min=min(t[x].min,v);      
			return; 
		} 
		int mid=(l+r)>>1; 
		if(p<=mid) update(lson,l,mid,p,v); 
		else update(rson,mid+1,r,p,v); 
		pushup(x); 
	}   
	int query(int x,int l,int r,int L,int R) 
	{
		if(!x) return inf; 
		if(l>=L&&r<=R) return t[x].min;     
		int mid=(l+r)>>1,re=inf; 
		if(L<=mid) re=min(re,query(lson,l,mid,L,R)); 
		if(R>mid)  re=min(re,query(rson,mid+1,r,L,R));      
		return re;    
	}
	#undef lson 
	#undef rson  
}; 
int root,sn;
int size[N],Fa[N],mx[N],vis[N],rt[N]; 
void getroot(int u,int ff)
{ 
	size[u]=1,mx[u]=0; 
	for(int i=hd[u];i;i=nex[i]) 
		if(to[i]!=ff&&!vis[to[i]]) 
			getroot(to[i],u),size[u]+=size[to[i]],mx[u]=max(mx[u],size[to[i]]); 
	mx[u]=max(mx[u],sn-mx[u]);    
	if(mx[u]<mx[root]) root=u;
}  
void dfs(int u,int ff)
{
	size[u]=1; 
	for(int i=hd[u];i;i=nex[i]) 
		if(to[i]!=ff&&!vis[to[i]]) 
			dfs(to[i],u),size[u]+=size[to[i]]; 
}     
void calc(int u,int ff,int dep,int tp) 
{    
	seg::update(rt[tp],1,n,u,dep);           
	for(int i=hd[u];i;i=nex[i]) 
		if(to[i]!=ff&&!vis[to[i]]) 
			calc(to[i],u,dep+val[i],tp);     
}
void prepare(int u) 
{ 
	vis[u]=1,calc(u,0,0,u);        
	for(int i=hd[u];i;i=nex[i]) 
		if(!vis[to[i]]) 
			dfs(to[i],u),root=0,sn=size[to[i]],getroot(to[i],u),Fa[root]=u,prepare(root);     
}
int query(int u,int l,int r) 
{
	int re=seg::query(rt[u],1,n,l,r),U=u;           
	for(;Fa[u];u=Fa[u]) 
		re=min(re, seg::query(rt[Fa[u]],1,n,l,r)+tree::Dis(U,Fa[u]));      
	return re;       
}
int main() 
{ 
	int i,j,m; 
	// setIO("input");  
	scanf("%d",&n); 
	for(i=1;i<n;++i) 
	{
		int a,b,c; 
		scanf("%d%d%d",&a,&b,&c),add(a,b,c),add(b,a,c); 
	} 
	tree::dfs1(1,0),tree::dfs2(1,1);      
	root=0,mx[root]=sn=n,getroot(1,0),prepare(root);  
	scanf("%d",&m); 
	for(i=1;i<=m;++i) 
	{
		int l,r,x; 
		scanf("%d%d%d",&l,&r,&x);      
		printf("%d\n",query(x,l,r));     
	}
	return 0; 
}

  

猜你喜欢

转载自www.cnblogs.com/guangheli/p/11456762.html