Codeforces 739B(树上路径倍增及差分)
2016-12-15 20:26
302 查看
比较考验我思维的一道好题。
首先,做一遍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)
代码送上。
首先,做一遍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)
代码送上。
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i(0); i < (n); ++i) #define rep(i,a,b) for(int i(a); i <= (b); ++i) #define dec(i,a,b) for(int i(a); i >= (b); --i) #define for_edge(i,x) for(int i = H[x]; i; i = X[i]) #define LL long long #define ULL unsigned long long #define MP make_pair #define PB push_back #define FI first #define SE second #define INF 1 << 30 #define sz(x) (int)x.size() const int N = 200000 + 10; const int M = 10000 + 10; const int Q = 1000 + 10; const int A = 30 + 1; vector <int> v , c ; LL a , deep ; LL x, y; int n, cnt; LL t [A], d [A]; LL g , value ; LL s ; LL ans ; void dfs(int x, int fa){ if (g[x]){ t[x][0] = g[x]; d[x][0] = value[x]; for (int i = 0; t[t[x][i]][i]; ++i){ t[x][i + 1] = t[t[x][i]][i]; d[x][i + 1] = d[t[x][i]][i] + d[x][i]; } int now = x, noww = 0; bool flag = false; dec(i, 20, 0){ if (t[now][i] && d[now][i] + noww <= a[x]){ noww += d[now][i]; now = t[now][i]; flag = true; } } if (flag){ --s[g[now]]; ++s[g[x]]; } } REP(i, sz(v[x])){ int u = v[x][i]; deep[u] = deep[x] + 1; dfs(u, x); } } void dfs2(int x){ ans[x] += s[x]; REP(i, sz(v[x])){ dfs2(v[x][i]); ans[x] += ans[v[x][i]]; } } int main(){ #ifndef ONLINE_JUDGE freopen("test.txt", "r", stdin); freopen("test.out", "w", stdout); #endif scanf("%d", &n); rep(i, 1, n) scanf("%lld", a + i); rep(i, 2, n){ scanf("%lld%lld", &x, &y); g[i] = x; value[i] = y; v[x].PB(i), c[x].PB(y); } memset(s, 0, sizeof s); cnt = 0; deep[1] = 0; dfs(1, 0); memset(ans, 0, sizeof ans); dfs2(1); rep(i, 1, n - 1) printf("%lld ", ans[i]); printf("%lld\n", ans ); return 0; }
相关文章推荐
- 【CF739B】Alyona and a tree(树上差分,二分,树形DP)
- Codeforces 740D Alyona and a tree 二分+树上差分
- HDU 4718 The LCIS on the Tree 树上路径倍增
- 【CodeForces】983 E. NN country 树上倍增+二维数点
- noip2013truck树上路径倍增
- 【NOIP2016提高组T2】天天爱跑步-倍增LCA+树上差分
- Codeforces 739B【树上倍增+差分】
- 【图论,树上路径倍增算法】NOIP2013货车运输
- noip运输计划(倍增lca,树上差分)
- CodeForces - 842C Ilya And The Tree(树上倍增)
- codeforces 587C(树上的倍增算法)
- CodeForces 932D Tree(树上倍增)
- 739B Codeforces Alyona and a tree 树上差分+二分(倍增)
- Codeforces 932D Tree 树上倍增
- [JLOI2014]松鼠的新家 倍增LCA+树上差分
- Codeforces 19E 树上差分
- CodeForces 832D Round #425 D Misha, Grisha and Underground :LCA求树上路径长度
- [JLOI2014][BZOJ3631] 松鼠的新家|树上倍增LCA|差分
- [codeforces 519E]E. A and B and Lecture Rooms(树上倍增)
- Codeforces 932D - Tree 【树上倍增】