5055 樹上路徑

2021-07-30 14:13:37 字數 1509 閱讀 5083

給定一顆

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 個城堡。每個城堡恰好屬於乙個領主。不同的城堡屬於不同的領主。在所有領主中有乙個是國王,其他的每個領主都直接隸屬於另一位領主,並且間接隸屬於國王。一位領主可以擁有任意數量的下屬。這些城堡被一些雙向的道路連線。兩個城堡是連線的當且僅當他們的主人中一位直接隸屬於另一位。每一年,在...