5077. 树的难题
来源:互联网 发布:淘宝为什么刷关键词 编辑:程序博客网 时间:2024/05/16 14:54
题目大意
给定一棵
求树中经过边数在
Data Constraint
题解
考虑点剖,对于当前的分治重心,将每个儿子按照颜色排序。
然后维护两棵线段树即可。
时间复杂度:
SRC
#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std ;#define N 200000 + 10const int inf = 2e9 ;int T[2][4*N] ;bool vis[N] , Clear[2][4*N] ;int Node[2*N] , Next[2*N] , Col[2*N] , Head[N] , tot ;int C[N] , Size[N] , Maxs[N] , Son[N] , MaxDeep[N] , flag[N] , D[N][2] ;int n , m , L , R ;int Root , All , Minv , Cnt , MaxDep , tag ;int ans = -inf , ret , nowv ;int Read() { int ret = 0 , sign = 1 ; char ch = getchar() ; while ( ch < '0' || ch > '9' ) { if ( ch == '-' ) sign = -1 ; ch = getchar() ; } while ( ch >= '0' && ch <= '9' ) { ret = ret * 10 + ch - '0' ; ch = getchar() ; } return sign * ret ;}void link( int u , int v , int w ) { Node[++tot] = v ; Next[tot] = Head[u] ; Col[tot] = w ; Head[u] = tot ;}bool cmp( int a , int b ) { return Col[a] < Col[b] ; }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 ) Root = x , Minv = Maxs[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 , int last , int sum , int deep ) { if ( flag[deep] != tag ) { flag[deep] = tag ; MaxDeep[deep] = -inf ; MaxDep = max( MaxDep , deep ) ; } MaxDeep[deep] = max( MaxDeep[deep] , sum ) ; if ( deep >= L && deep <= R ) ans = max( ans , sum ) ; D[++Cnt][0] = deep , D[Cnt][1] = sum ; for (int p = Head[x] ; p ; p = Next[p] ) { if ( Node[p] == F || vis[Node[p]] ) continue ; DFS( Node[p] , x , Col[p] , sum + (Col[p] != last) * C[Col[p]] , deep + 1 ) ; }}void Insert( int type , int v , int l , int r , int x , int val ) { if ( l == r ) { T[type][v] = max( T[type][v] , val ) ; return ; } if ( Clear[type][v] ) { T[type][v+v] = -inf ; T[type][v+v+1] = -inf ; Clear[type][v+v] = Clear[type][v+v+1] = 1 ; Clear[type][v] = 0 ; } int mid = (l + r) >> 1 ; if ( x <= mid ) Insert( type , v + v , l , mid , x , val ) ; else Insert( type , v + v + 1 , mid + 1 , r , x , val ) ; T[type][v] = max( T[type][v+v] , T[type][v+v+1] ) ;}void Search( int type , int v , int l , int r , int x , int y ) { if ( nowv + T[type][v] <= ans || T[type][v] <= ret ) return ; if ( l == x && r == y ) { ret = max( ret , T[type][v] ) ; return ; } if ( Clear[type][v] ) { T[type][v+v] = -inf ; T[type][v+v+1] = -inf ; Clear[type][v+v] = Clear[type][v+v+1] = 1 ; Clear[type][v] = 0 ; } int mid = (l + r) >> 1 ; if ( y <= mid ) Search( type , v + v , l , mid , x , y ) ; else if ( x > mid ) Search( type , v + v + 1 , mid + 1 , r , x , y ) ; else { Search( type , v + v , l , mid , x , mid ) ; Search( type , v + v + 1 , mid + 1 , r , mid + 1 , y ) ; } T[type][v] = max( T[type][v+v] , T[type][v+v+1] ) ;}void Solve( int x ) { Root = All = x , Minv = inf ; GetSize( x , 0 ) ; GetRoot( x , 0 ) ; vis[Root] = 1 ; Son[0] = 0 ; for (int p = Head[Root] ; p ; p = Next[p] ) { if ( vis[Node[p]] ) continue ; Son[++Son[0]] = p ; } sort( Son + 1 , Son + Son[0] + 1 , cmp ) ; Clear[0][1] = 1 ; T[0][1] = -inf ; MaxDep = 0 ; for (int i = 1 ; i <= Son[0] ; i ++ ) { int p = Son[i] ; if ( i == 1 || Col[p] != Col[Son[i-1]] ) { Clear[1][1] = 1 , tag ++ ; T[1][1] = -inf ; for (int k = 1 ; k <= MaxDep ; k ++ ) { Insert( 0 , 1 , 1 , n , k , MaxDeep[k] ) ; } MaxDep = 0 ; } Cnt = 0 ; DFS( Node[p] , Root , Col[p] , C[Col[p]] , 1 ) ; for (int k = 1 ; k <= Cnt ; k ++ ) { int deep = D[k][0] , val = D[k][1] ; nowv = val ; if ( R > deep && i > 1 && val + T[0][1] > ans ) { ret = -inf ; Search( 0 , 1 , 1 , n , max( L - deep , 1 ) , R - deep ) ; ans = max( ans , val + ret ) ; } if ( i > 1 && R > deep && Col[p] == Col[Son[i-1]] && val + T[1][1] - C[Col[p]] > ans ) { ret = -inf ; nowv -= C[Col[p]] ; Search( 1 , 1 , 1 , n , max( L - deep , 1 ) , R - deep ) ; ans = max( ans , val + ret - C[Col[p]] ) ; } } for (int k = 1 ; k <= Cnt ; k ++ ) Insert( 1 , 1 , 1 , n , D[k][0] , D[k][1] ) ; } for (int p = Head[Root] ; p ; p = Next[p] ) { if ( vis[Node[p]] ) continue ; Solve( Node[p] ) ; }}int main() { freopen( "journey.in" , "r" , stdin ) ; freopen( "journey.out" , "w" , stdout ) ; scanf( "%d%d%d%d" , &n , &m , &L , &R ) ; for (int i = 1 ; i <= m ; i ++ ) C[i] = Read() ; for (int i = 1 ; i < n ; i ++ ) { int u = Read() , v = Read() , w = Read() ; link( u , v , w ) ; link( v , u , w ) ; } Solve( (n + 1) / 2 ) ; printf( "%d\n" , ans ) ; return 0 ;}
以上.
1 0
- 5077. 树的难题
- 树的难题
- 树的难题
- [JZOJ5077]树的难题
- [bzoj4860]树的难题
- [BZOJ 3257]树的难题
- 1900: 985的“树”难题
- 1900: 985的“树”难题
- 【GDOI2017模拟】树的难题
- 统计难题(字典树的应用)
- 【郑轻】[1900]985的“树”难题
- zzulioj 1900(985的“树”难题)
- zzulioj-1900: 985的“树”难题
- zzuli 1990 985的“树”难题
- 【zzulioj 1900 985的“树”难题】
- [BZOJ]3257树的难题 树型DP
- 现在的难题
- 需求的难题
- 大型项目架构演进过程及思考的点
- 云服务器
- android:gravity与android:layout_gravity疑点
- bzoj4010 [HNOI2015]菜肴制作 拓补排序+堆
- [系分] 初始阶段
- 5077. 树的难题
- JAVA自定义异常
- 复习JQ (7)
- 时光已经远去,你还在犹豫什么?
- 腾讯拦截网站解决方案
- 模拟退火算法
- 剑指offer:(11)代码的完整性: 数值的整数次方
- VIM快捷(一):移动
- shell知识体系框图