[POI2014]MRO-Ant colony

嘟嘟嘟

题面很迷,看这个吧。

首先暴力很简单,从每一个叶子节点开始爬,直到那条特殊的边。

正解稍微想想就能搞出来:(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 }
View Code
原文地址:https://www.cnblogs.com/mrclr/p/9837592.html