Codeforces 739B【树上倍增+差分】
2017-08-09 22:39
417 查看
思路:
差分其实是个自己随便创造的东西啊~
差分(这里的小差分):
比如你要算一棵树上 u->v 路径上的次数, v是 u 子树上的一个点,
算一棵树上 u->v 路径上的次数 在这了是算u -> v路径上除了 v 的 每个节点的次数,
对于每一对u, v (u -> v)的,用C[i]计数,可以C[fa[ u ]]–, C[fa[ v ]]++ (fa[i] 是 i 的前驱节点), 然后跑一下DFS,统计次数,具体处理就是对于每个节点去加上他的所有子节点的次数,然后就会发现就这么搞好了。。
树上倍增:
福利:真讲的超级棒!!!
处理完倍增以后,就是每次找一个能“跳”的最远位置!
要多刷一波倍增的题了!!!
代码参考自:http://blog.csdn.net/cabinfever/article/details/53325717
差分其实是个自己随便创造的东西啊~
差分(这里的小差分):
比如你要算一棵树上 u->v 路径上的次数, v是 u 子树上的一个点,
算一棵树上 u->v 路径上的次数 在这了是算u -> v路径上除了 v 的 每个节点的次数,
对于每一对u, v (u -> v)的,用C[i]计数,可以C[fa[ u ]]–, C[fa[ v ]]++ (fa[i] 是 i 的前驱节点), 然后跑一下DFS,统计次数,具体处理就是对于每个节点去加上他的所有子节点的次数,然后就会发现就这么搞好了。。
树上倍增:
福利:真讲的超级棒!!!
处理完倍增以后,就是每次找一个能“跳”的最远位置!
对于第一次应用倍增和差分,真是感觉非常...爽啊...
要多刷一波倍增的题了!!!
代码参考自:http://blog.csdn.net/cabinfever/article/details/53325717
#include<iostream> #include<cstdio> #include<queue> #include<vector> #include<string.h> #include<algorithm> using namespace std; typedef long long LL; #define mem(a,b) memset(a, b, sizeof(a)) #define LMid Left, Mid #define RMid Mid+1,Right #define Lson num<<1, Left, Mid #define Rson num<<1|1, Mid + 1, Right const int Maxn = 2e5 + 10; struct Edge{int v,nex;LL w;}edge[Maxn<<1]; int n, head[Maxn], tol, f[Maxn][23]; LL w[Maxn], c[Maxn], dis[Maxn]; void init(){mem(head,-1);tol = 0;} void add(int u,int v, LL w){ edge[tol] = (Edge){v, head[u], w}, head[u] = tol++; edge[tol] = (Edge){u, head[v], w}, head[v] = tol++; } void DFS1(int u, int fa){ int v, x = u; f[u][0] = fa; for(int i=1;i<20;i++) f[u][i] = f[f[u][i-1]][i-1]; for(int i=19;i>=0;i--) while(x > 1 && dis[u] - dis[f[x][i]] <= w[u]) x = f[x][i]; x = max(1, x); c[f[x][0]]--; c[f[u][0]]++; for(int i=head[u];~i;i=edge[i].nex){ v = edge[i].v; if(v == fa) continue; dis[v] = dis[u] + edge[i].w; DFS1(v, u); } } void DFS2(int u, int fa){ int v; for(int i=head[u];~i;i=edge[i].nex){ v = edge[i].v; if(v == fa) continue; DFS2(v, u); c[u] += c[v]; } } int main(){ int p; LL q; scanf("%d", &n); for(int i=1;i<=n;i++) scanf("%I64d", &w[i]); init(); for(int i=2;i<=n;i++){ scanf("%d%I64d",&p, &q); add(i, p, q); } DFS1(1, 0); DFS2(1, 0); for(int i=1;i<=n;i++) printf("%I64d ", c[i]); return 0; }
相关文章推荐
- Codeforces 739B(树上路径倍增及差分)
- Codeforces 600E Lomsat gelral 树上启发式合并
- Codeforces 932D - Tree 【树上倍增】
- CodeForces 932D Tree(树上倍增)
- Codeforces 587C【树上倍增】
- CodeForces 682C Alyona and the Tree (树上DFS)
- CodeForces 915F Imbalance Value of a Tree(并查集+树上统计)
- CodeForces 280C 浅谈期望线性性的树上问题实际运用
- CodeForces 690C2 Brain Network (树上最大距离)
- Codeforces 932D Tree 树上倍增
- CodeForces - 486D Valid Sets(树上的DP计数)
- 【CodeForces】983 E. NN country 树上倍增+二维数点
- Codeforces 453C Little Pony and Summer Sun Celebration dfs树上构造
- Codeforces 455B A Lot of Games 字典树上博弈
- [codeforces 519E]E. A and B and Lecture Rooms(树上倍增)
- Codeforces 827D (Round #423 Div. 1) D. Best Edge Weight 树上倍增
- Codeforces 740D Alyona and a tree 二分+树上差分
- 【CF739B】Alyona and a tree(树上差分,二分,树形DP)
- Codeforces 842C - Ilya And The Tree 【树上DFS】
- CodeForces 690C2 Brain Network (medium)(树上DP)