JZOJ3997. 树
来源:互联网 发布:小区网络装iptv服务器 编辑:程序博客网 时间:2024/06/06 12:53
题目大意
给定一棵
每个询问,查询编号在
强制在线。
Data Constraint
题解
考虑点剖。先构出点剖树,每个结点维护一棵线段树。
然后对于每一个询问在点剖树上跑,每次查询线段树上对应的区间。
时间复杂度:
SRC
#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std ;#define N 100000 + 10typedef long long ll ;const int MAXN = 18 ;struct Tree { int Son[2] ; int val ;} T[100*N] ;bool vis[N] ;int f[N][MAXN] , Deep[N] ;int Node[2*N] , Next[2*N] , Len[2*N] , Head[N] , tot ;int Size[N] , Maxs[N] , Dis[N] , Dist[N] , fa[N] , Rt[N] ;int Root , All , Minv , ret ;int n , m , Cnt ;ll ans ;void link( int u , int v , int w ) { Node[++tot] = v ; Len[tot] = w ; Next[tot] = Head[u] ; Head[u] = tot ;}int NewNode() { ++ Cnt ; T[Cnt].Son[0] = T[Cnt].Son[1] = 0 ; T[Cnt].val = 0 ; return Cnt ;}void Insert( int v , int l , int r , int x , int val ) { if ( l == x && r == x ) { T[v].val = val ; return ; } int mid = (l + r) / 2 ; if ( x <= mid ) { if ( !T[v].Son[0] ) T[v].Son[0] = NewNode() ; Insert( T[v].Son[0] , l , mid , x , val ) ; } else { if ( !T[v].Son[1] ) T[v].Son[1] = NewNode() ; Insert( T[v].Son[1] , mid + 1 , r , x , val ) ; } T[v].val = min( T[T[v].Son[0]].val , T[T[v].Son[1]].val ) ;}void Search( int v , int l , int r , int x , int y ) { if ( !v ) return ; if ( l == x && r == y ) { ret = min( ret , T[v].val ) ; return ; } int mid = (l + r) / 2 ; if ( y <= mid ) Search( T[v].Son[0] , l , mid , x , y ) ; else if ( x > mid ) Search( T[v].Son[1] , mid + 1 , r , x , y ) ; else { Search( T[v].Son[0] , l , mid , x , mid ) ; Search( T[v].Son[1] , mid + 1 , r , mid + 1 , y ) ; }}void GetSize( int x , int F ) { Size[x] = Maxs[x] = 1 ; for (int p = Head[x] ; p ; p = Next[p] ) { if ( Node[p] == F || vis[Node[p]] ) continue ; GetSize( Node[p] , x ) ; Size[x] += Size[Node[p]] ; if ( Size[Node[p]] > Maxs[x] ) Maxs[x] = Size[Node[p]] ; }}void GetRoot( int x , int F ) { Maxs[x] = max( Maxs[x] , Size[All] - Maxs[x] ) ; if ( Maxs[x] < Minv ) Minv = Maxs[x] , Root = x ; for (int p = Head[x] ; p ; p = Next[p] ) { if ( Node[p] == F || vis[Node[p]] ) continue ; GetRoot( Node[p] , x ) ; }}void DFS( int x , int F ) { for (int p = Head[x] ; p ; p = Next[p] ) { if ( vis[Node[p]] || Node[p] == F ) continue ; Dis[Node[p]] = Dis[x] + Len[p] ; Insert( Rt[Root] , 1 , n , Node[p] , Dis[Node[p]] ) ; DFS( Node[p] , x ) ; }}void DIV( int x , int F ) { GetSize( x , 0 ) ; Minv = 0x7FFFFFFF ; Root = All = x ; GetRoot( x , 0 ) ; vis[Root] = 1 ; fa[Root] = F ; Rt[Root] = ++ Cnt ; Insert( Rt[Root] , 1 , n , Root , 0 ) ; Dis[Root] = 0 ; for (int p = Head[Root] ; p ; p = Next[p] ) { if ( vis[Node[p]] ) continue ; Dis[Node[p]] = Len[p] ; Insert( Rt[Root] , 1 , n , Node[p] , Dis[Node[p]] ) ; DFS( Node[p] , Root ) ; } int now = Root ; for (int p = Head[Root] ; p ; p = Next[p] ) { if ( vis[Node[p]] ) continue ; DIV( Node[p] , now ) ; }}void Pre( int x ) { for (int p = Head[x] ; p ; p = Next[p] ) { if ( Node[p] == f[x][0] ) continue ; f[Node[p]][0] = x ; Deep[Node[p]] = Deep[x] + 1 ; Dist[Node[p]] = Dist[x] + Len[p] ; Pre( Node[p] ) ; }}int LCA( int x , int y ) { if ( Deep[x] < Deep[y] ) swap( x , y ) ; for (int i = MAXN - 1 ; i >= 0 ; i -- ) { if ( Deep[f[x][i]] >= Deep[y] ) x = f[x][i] ; } if ( x == y ) return x ; for (int i = MAXN - 1 ; i >= 0 ; i -- ) { if ( f[x][i] != f[y][i] ) x = f[x][i] , y = f[y][i] ; } return f[x][0] ;}int Calc( int u , int v ) { return Dist[u] + Dist[v] - 2 * Dist[LCA(u,v)] ;}int main() { scanf( "%d" , &n ) ; for (int i = 1 ; i < n ; i ++ ) { int x , y , d ; scanf( "%d%d%d" , &x , &y , &d ) ; link( x , y , d ) ; link( y , x , d ) ; } Deep[1] = 1 ; Pre( 1 ) ; for (int j = 1 ; j < MAXN ; j ++ ) { for (int i = 1 ; i <= n ; i ++ ) f[i][j] = f[f[i][j-1]][j-1] ; } T[0].val = 0x7FFFFFFF ; DIV( 1 , 0 ) ; scanf( "%d" , &m ) ; ans = 0 ; for (int i = 1 ; i <= m ; i ++ ) { int L , R , pos ; scanf( "%d%d%d" , &L , &R , &pos ) ; pos ^= ans ; ans = 1e15 ; if ( pos >= L && pos <= R ) { ans = 0 ; printf( "0\n" ) ; continue ; } int now = pos ; while ( now ) { ret = 0x7FFFFFFF ; Search( Rt[now] , 1 , n , L , R ) ; ans = min( ans , (ll)Calc( pos , now ) + ret ) ; now = fa[now] ; } printf( "%lld\n" , ans ) ; } return 0 ;}
以上.
1 0