《定义》
对于原数列:a1 a2 a3.....ai aj........an-1 an
这个数列的差分为ca[j]=aj-ai
这个数列的前缀和为he[j]=aj+ai+..+a2+a1
我们可以惊奇的发现
差分的前缀和==原数列
前缀和的差分==原数列
利用这个性质:
《树上差分》
比如这道题:
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <vector> 5 using namespace std; 6 const int N = 100005; 7 vector<int> tree[N]; 8 // ca[i]表示点i管理的边权的差分; 9 // ans[i]表示点i管理的边权; 10 //树上差分,叶子节点开始,根节点为停止 11 int ca[N], ans[N]; 12 int sizer[N], f[N], dep[N], son[N]; 13 void dfs1(int x, int from, int d) 14 { 15 f[x] = from, dep[x] = d, sizer[x] = 1, son[x] = -1; 16 for (int i = 0; i < tree[x].size(); i++) 17 { 18 int child = tree[x][i]; 19 if (child == from) 20 continue; 21 dfs1(child, x, d + 1); 22 sizer[x] += sizer[child]; 23 if (son[x] == -1 || sizer[son[x]] < sizer[child]) 24 son[x] = child; 25 } 26 } 27 int top[N], id[N], rk[N], cnt = 0; 28 void dfs2(int x, int from, int t) 29 { 30 ++cnt; 31 id[x] = cnt, rk[cnt] = x, top[x] = t; 32 if (son[x] != -1) 33 dfs2(son[x], x, t); 34 for (int i = 0; i < tree[x].size(); i++) 35 { 36 int child = tree[x][i]; 37 if (child == from || child == son[x]) 38 continue; 39 dfs2(child, x, child); 40 } 41 } 42 int lca(int a, int b) 43 { 44 while (top[a] != top[b]) 45 { 46 if (dep[top[a]] < dep[top[b]]) 47 swap(a, b); 48 a = f[top[a]]; 49 } 50 if (dep[a] > dep[b]) 51 swap(a, b); 52 return a; 53 } 54 void preSum(int x, int from) 55 { 56 ans[x] = ca[x]; 57 for (int i = 0; i < tree[x].size(); i++) 58 { 59 int child = tree[x][i]; 60 if (child == from) 61 continue; 62 //总之,先到叶子节点 63 preSum(child, x); 64 ans[x] += ans[child]; 65 /* cout << "! " 66 << "child " << child << " " 67 << "ans[child] " << ans[child] << " " 68 << "node:" << x << " " 69 << "ans[x] " << ans[x] << endl; */ 70 } 71 } 72 int main() 73 { 74 int n; 75 scanf("%d", &n); 76 pair<int, int> side[N]; 77 for (int i = 1; i <= n - 1; i++) 78 { 79 int a, b; 80 scanf("%d%d", &a, &b); 81 side[i] = {a, b}; 82 tree[a].push_back(b), tree[b].push_back(a); 83 } 84 //用树剖求解lca 85 dfs1(1, -1, 1); 86 dfs2(1, -1, 1); 87 int m; 88 scanf("%d", &m); 89 while (m--) 90 { 91 int x, y; 92 scanf("%d%d", &x, &y); 93 if (dep[x] < dep[y]) 94 swap(x, y); 95 //因为这里改变的权重为1,直接++即可 96 if (top[x] != top[y]) 97 ca[x]++, ca[y]++, ca[lca(x, y)] -= 2; 98 else 99 ca[x]++, ca[y]--; 100 } 101 preSum(1, -1); 102 for (int i = 1; i <= n - 1; i++) 103 { 104 int x = side[i].first, y = side[i].second; 105 if (dep[x] < dep[y]) 106 swap(x, y); 107 printf("%d ", ans[x]); 108 } 109 return 0; 110 }
标签:少次,int,top,tree,差分,son,----,child,区间 From: https://www.cnblogs.com/cilinmengye/p/16625275.html