首页 > 代码库 > Codeforces 739B Alyona and a tree (树上路径倍增及差分)

Codeforces 739B Alyona and a tree (树上路径倍增及差分)

题目链接 Alyona and a tree

弄了好几个小时终于Accepted了,之后发现这个题是Div1的。

比较考验我思维的一道好题。

首先,做一遍DFS预处理出t[i][j]和d[i][j]。t[i][j]表示从第i个节点到离他第2^j近的祖先,d[i][j]表示从i开始到t[i][j]的路径上的路径权值总和。

在第一次DFS的同时,对节点x进行定位(结果为dist(x, y)<=a(y))的离x最远的x的某个祖先,然后进行O(1)的差分。

第一次DFS完成后,做第二次DFS统计答案(统计差分后的结果)。时间复杂度为O(NlgN)

代码送上。

 

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define REP(i,n)                for(int i(0); i <  (n); ++i)
 6 #define rep(i,a,b)              for(int i(a); i <= (b); ++i)
 7 #define dec(i,a,b)              for(int i(a); i >= (b); --i)
 8 #define for_edge(i,x)           for(int i = H[x]; i; i = X[i])
 9 
10 #define LL      long long
11 #define ULL     unsigned long long
12 #define MP      make_pair
13 #define PB      push_back
14 #define FI      first
15 #define SE      second
16 #define INF     1 << 30
17 #define sz(x)    (int)x.size()
18 
19 const int N     =    200000      +       10;
20 const int M     =    10000       +       10;
21 const int Q     =    1000        +       10;
22 const int A     =    30          +       1;
23 
24 
25 vector <int> v[N], c[N];
26 LL a[N], deep[N];
27 LL x, y;
28 int n, cnt;
29 LL t[N][A], d[N][A];
30 LL g[N], value[N];
31 LL s[N];
32 LL ans[N];
33 
34 void dfs(int x, int fa){
35     if (g[x]){
36         t[x][0] = g[x];
37         d[x][0] = value[x];
38         for (int i = 0; t[t[x][i]][i]; ++i){
39             t[x][i + 1] = t[t[x][i]][i];
40             d[x][i + 1] = d[t[x][i]][i] + d[x][i];
41         }
42         int now = x, noww = 0;
43         bool flag = false;
44         dec(i, 20, 0){
45             if (t[now][i] && d[now][i] + noww <= a[x]){
46                 noww += d[now][i];
47                 now = t[now][i];
48                 flag = true;
49             }
50         }
51         if (flag){
52             --s[g[now]]; ++s[g[x]];
53         }
54     }
55 
56     REP(i, sz(v[x])){
57         int u = v[x][i];
58         deep[u] = deep[x] + 1;
59         dfs(u, x);
60     }
61 }
62 
63 void dfs2(int x){
64     ans[x] += s[x];
65     REP(i, sz(v[x])){
66         dfs2(v[x][i]);
67         ans[x] += ans[v[x][i]];
68     }
69 }
70 
71 int main(){
72 
73     scanf("%d", &n);
74     rep(i, 1, n) scanf("%lld", a + i);
75     rep(i, 2, n){
76         scanf("%lld%lld", &x, &y); g[i] = x; value[i] = y;
77         v[x].PB(i), c[x].PB(y);
78     }
79 
80     memset(s, 0, sizeof s);
81     cnt = 0;
82     deep[1] = 0;
83     dfs(1, 0);
84     memset(ans, 0, sizeof ans);
85     dfs2(1);
86     rep(i, 1, n - 1) printf("%lld ", ans[i]);
87     printf("%lld\n", ans[n]);
88 
89     return 0;
90 
91 }

 

Codeforces 739B Alyona and a tree (树上路径倍增及差分)