站外sexy线段树 在线求调
  • 板块灌水区
  • 楼主wyf_sinon
  • 当前回复3
  • 已保存回复3
  • 发布时间2024/7/18 18:34
  • 上次更新2024/7/18 19:26:01
查看原帖
站外sexy线段树 在线求调
540177
wyf_sinon楼主2024/7/18 18:34

题干大意:

有一棵树,每次询问点集l1-r1与l2-r2之间的最大距离

蒟蒻用线段树维护的

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ls pos<<1
#define rs pos<<1|1
const int N=1e6+10;
int n,q;
int h[N],ver[N*2],edge[N*2],ne[N*2],idx;
int dis[N];
void link( int u , int v , int w )
{
    ne[idx] = h[u] ;
    edge[idx] = w ;
    ver[idx] = v ;
    h[u] = idx++ ;
}
int fa[N],Size[N],son[N],dep[N];
void dfs1( int x , int f , int w )
{
	Size[x] = 1 ;
    dep[x] = dep[f] + 1 ;
    fa[x] = f ;
    son[x] = -1 ;
    dis[x] = dis[f] + w ;
    for( int i = h[x] ; ~i ; i = ne[i] )
    {
    	int y = ver[i] ;
    	if( y == f ) continue ;
    	dfs1( y , x , edge[i] ) ;
    	Size[x] += Size[y] ;
    	if( son[x]==-1 || Size[y] > Size[son[x]] ) son[x] = y ; // 重链 
	}
}
int rnk[N],dfn[N],top[N],T;
void dfs2( int x , int t )
{
  	dfn[x] = ++T ;
  	rnk[T] = x ;
  	top[x] = t ;
  	if( son[x] == -1 ) return ;
  	dfs2 (son[x] , t ) ; // 优先遍历重链
  	for( int i = h[x] ; ~i ; i = ne[i] )
  	{
  		int y = ver[i] ;
  		if( y == fa[x] || y== son[x] ) continue ;
  		dfs2( y , y ) ;
	}
}
int LCA( int u , int v )
{
	while( top[u] != top[v] )
	{
		if( dep[u] < dep[v] ) swap( u , v ) ;
		u = fa[top[u]] ;
	}
	return dep[u]>dep[v] ? v : u ;
}
int Distant( int u , int v )
{
	int z = LCA ( u , v ) ;
	return dis[u] + dis[v] - dis[z] * 2 ; 
}
struct Segment_Tree
{
	int l,r;
	int diameter_l,diameter_r;//直径两端点的编号 dfn连续 rnk查询点
	int d;
}tree[N*4]; 
Segment_Tree merge( Segment_Tree a , Segment_Tree b )
{ 
	Segment_Tree new_tree ;
	int l1 = a.diameter_l , r1 = a.diameter_r ;
	int l2 = b.diameter_l , r2 = b.diameter_r ;
	int L = a.l , R = b.r ;
	int x1 = Distant ( l1 , l2 ) , x2 = Distant ( l1 , r2 ) , x3 = Distant ( r1 , l2 ) , x4 = Distant ( r1 , r2 ) ;
	if ( x1 >= x2 && x1 >= x3 && x1 >= x4 )
	{
		new_tree.diameter_l = l1 ;
		new_tree.diameter_r = l2 ;
		new_tree.d = x1 ;
	}
	else if ( x2 >= x1 && x2 >= x3 && x2 >= x4 )
	{
		new_tree.diameter_l = l1 ;
		new_tree.diameter_r = r2 ;
		new_tree.d = x2 ;
	}
	else if ( x3 >= x1 && x3 >= x2 && x3 >= x4 )
	{
		new_tree.diameter_l = r1 ;
		new_tree.diameter_r = l2 ;
		new_tree.d = x3 ;
	}
	else 
	{
		new_tree.diameter_l = r1 ;
		new_tree.diameter_r = r2 ;
		new_tree.d = x4 ;
	}
	if ( a.d > new_tree.d ) 
	{
		new_tree.diameter_l = l1 ;
		new_tree.diameter_r = r1 ;
		new_tree.d = a.d ;
	}
	if ( b.d > new_tree.d ) 
	{
		new_tree.diameter_l = l2 ;
		new_tree.diameter_r = r2 ;
		new_tree.d = b.d ;
	}
	new_tree.l = L ; new_tree.r = R ;
	return new_tree;
} 
void update(int pos) // merge 点集 
{
	tree[pos] = merge ( tree[ls] , tree[rs] ) ; 
	tree[pos].l = tree[ls].l ; tree[pos].r = tree[rs].r ; 
}
void build(int pos,int l,int r)
{ 
	tree[pos].l = l ; tree[pos].r = r ; 
	if( l == r ) { tree[pos].diameter_l = l ; tree[pos].diameter_r = l ; return ; }
	int mid = l + r >> 1 ;
	build( ls , l , mid ) ;
	build( rs , mid + 1 , r ) ;
	update( pos ) ;
}
Segment_Tree query( int pos , int l , int r ) // 返回结构体 因为合并需要子节点信息 
{  
	if( l <= tree[pos].l && tree[pos].r <= r ) return tree[pos] ;  
	int mid = tree[pos].l + tree[pos].r >> 1 ; 
	if( mid < l ) return query( rs , l , r ) ; 
	if( mid + 1 > r  ) return query( ls , l , r ) ;
	return merge( query( ls , l , r ) , query( rs , l , r ) ) ;
}
signed main()
{
	memset( h , -1 , sizeof h ) ;
    scanf("%lld%lld",&n,&q); 
    for( int i = 1 ; i < n ; i++ )
    {
        int u,v,w;
        scanf("%lld%lld%lld",&u,&v,&w);
        link( u , v , w ) ; link( v , u , w ) ;
    }
    dfs1( 1 , 0 , 0 ) ; 
    dfs2( 1 , 1 ) ; 
    build( 1 , 1 , n ) ;    
    for( int i = 1 ; i <= q ; i++ ) 
    { 
    	int l1,r1,l2,r2;
    	scanf("%lld%lld%lld%lld",&l1,&r1,&l2,&r2) ;
    	int ans = 0 ;
    	Segment_Tree x = query( 1 , l1 , r1 ) , y = query( 1 , l2 , r2 ) ; 
    	int u , v , w ;
    	u = x.diameter_l , v = y.diameter_l ; w = Distant( u , v ) ; if( w > ans ) ans = w ; 
    	u = x.diameter_l , v = y.diameter_r ; w = Distant( u , v ) ; if( w > ans ) ans = w ; 
    	u = x.diameter_r , v = y.diameter_l ; w = Distant( u , v ) ; if( w > ans ) ans = w ; 
    	u = x.diameter_r , v = y.diameter_r ; w = Distant( u , v ) ; if( w > ans ) ans = w ; 
    	printf("%lld\n",ans) ; 
	}
}
2024/7/18 18:34
加载中...