题面很迷,看这个吧。
首先暴力很简单,从每一个叶子节点开始爬,直到那条特殊的边。
正解稍微想想就能搞出来:(x, y)这条特殊的边把整棵树分成了两部分,然后我们分别从x, y开始在他的那部分子树dfs,求出到达节点v时满足条件的一个区间。因为从v到u是向下取整,那么反过来合法的区间就是[k * (du[u] - 1), k * (du[u] - 1) + (du[u] - 1) - 1]。
递归到叶子节点后在原序列中二分找在[Min, Max]中的数的个数,乘上k,累加到答案中。
时间复杂度O(nlogn)。
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 1e6 + 5; 21 const int MAX_NUM = 2e9; 22 inline ll read() 23 { 24 ll ans = 0; 25 char ch = getchar(), last = ' '; 26 while(!isdigit(ch)) {last = ch; ch = getchar();} 27 while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();} 28 if(last == '-') ans = -ans; 29 return ans; 30 } 31 inline void write(ll x) 32 { 33 if(x < 0) x = -x, putchar('-'); 34 if(x >= 10) write(x / 10); 35 putchar(x % 10 + '0'); 36 } 37 38 int n, m, k; 39 ll a[maxn]; 40 int s1, s2, du[maxn]; 41 ll ans = 0; 42 43 struct Edge 44 { 45 int nxt, to; 46 }e[maxn << 1]; 47 int head[maxn], ecnt = -1; 48 void addEdge(int x, int y) 49 { 50 e[++ecnt] = (Edge){head[x], y}; 51 head[x] = ecnt; 52 } 53 54 void dfs(int now, int f, ll Min, ll Max) 55 { 56 if(du[now] == 1) 57 { 58 int l = lower_bound(a + 1, a + m + 1, Min) - a; 59 int r = upper_bound(a + 1, a + m + 1, Max) - a - 1; 60 ans += (r - l + 1) * k; 61 return; 62 } 63 int x = du[now] - 1; 64 for(int i = head[now]; i != -1; i = e[i].nxt) 65 { 66 if(e[i].to == f) continue; 67 dfs(e[i].to, now, Min * x, Max * x + x - 1); 68 } 69 } 70 71 int main() 72 { 73 Mem(head, -1); 74 n = read(); m = read(); k = read(); 75 for(int i = 1; i <= m; ++i) a[i] = read(); 76 sort(a + 1, a + m + 1); 77 for(int i = 1; i < n; ++i) 78 { 79 int x = read(), y = read(); 80 du[x]++; du[y]++; 81 if(i == 1) s1 = x, s2 = y; 82 addEdge(x ,y); addEdge(y, x); 83 } 84 dfs(s1, s2, k, k); dfs(s2, s1, k, k); 85 write(ans), enter; 86 return 0; 87 }