給定一顆
n 個結點的無根樹,每個點有乙個點權,定義一條路徑的價值為路徑上的點權和-路徑的點權最大值。
給定引數
p,求有多少不同的樹上簡單路徑,滿足它的價值恰好是
p 的倍數。
data constraint n≤
105,p
≤107
考慮點分治。
對於當前的分治重心,把所有以它為起點的路徑取出來,按照路徑上點權的最大值排序。然後考慮如何計算答案。對於當前列舉到的第
i 條路徑,前面i−
1條路徑的最大值顯然都小於等於當前這條,所以可以直接維護乙個桶,每次在桶內查詢即可。
注意要去掉乙個子樹內部的路徑對答案的貢獻。
時間複雜度:o(
nlog
2n)
#include
#include
#include
#include
#include
using
namespace
std ;
#define n 100000 + 10
#define m 10000000 + 10
typedef
long
long ll ;
struct note
} d[n] , tp[n] ;
bool vis[n] ;
int node[2*n] , next[2*n] , head[n] , tot ;
int val[n] , size[n] , maxs[n] , t[m] ;
int n , mo ;
int root , all , minv , cnt , num ;
ll ans ;
bool cmp( note a , note b )
void link( int u , int v )
void getsize( int x , int f )
}void getroot( int x , int f )
}void dfs( int x , int f , int maxv , int sum )
}void calc( note *a , int n , int sig )
t[a[i].sum] ++ ;
}for (int i = 1 ; i <= n ; i ++ ) t[a[i].sum] -- ;
}void solve( int x )
calc( d , cnt , 1 ) ;
for (int p = head[root] ; p ; p = next[p] )
}int main()
for (int i = 1 ; i <= n ; i ++ ) scanf( "%d" , &val[i] ) ;
solve(1) ;
printf( "%lld\n" , ans + n ) ;
return
0 ;}
以上. JZOJ5055 樹上路徑
給定一棵 n 個節點的無根樹,每個點都有乙個非負整數的權值va li,定義一條路徑的價值為路徑上的點權和減去路徑的點權最大值。給定引數 p 請求出樹上有多少條價值是 p的倍數的路徑。注意 單點也算路徑。並且路徑 u v 和 v u 只算一次。1 n 105 1 p 107,0 va li 10 9 ...
題解 樹上路徑
一棵樹的構造過程為 首先以1號點為根,然後依次加入2 n號點。加入i號點時,在1 i 1點中選擇乙個點為f i 將i號點與其相連線。yuri想要求出,每次加點之後路上的最長路徑長度。第一行乙個整數n,表示樹的節點個數。第二行n 1個整數,第i個整數表示f i 1 一行n 1個整數,分別表示加完2 n...
樹上路徑(path)
在 berland,有n 個城堡。每個城堡恰好屬於乙個領主。不同的城堡屬於不同的領主。在所有領主中有乙個是國王,其他的每個領主都直接隸屬於另一位領主,並且間接隸屬於國王。一位領主可以擁有任意數量的下屬。這些城堡被一些雙向的道路連線。兩個城堡是連線的當且僅當他們的主人中一位直接隸屬於另一位。每一年,在...