首先我們需要注意一下的是,差分比較適用於修改比較多而查詢比較少的情況。
借教室 這是一道二分答案,在check函式中用到差分技巧的一道題,譬如說我們要把乙個序列中[l,r]區間都加上乙個權值,我們可以把在 l 處加上這個值,在r+1處減去這個值,再對記錄權值的陣列求字首和,那麼我們就可以得到這個真正的權值陣列。
題解 在鏈結裡,**就不放了=w=。
樹上差分可以分為在點權上的情況和 在邊權上的情況。
1: 點權 :
比如在樹上把 從u到v的路徑的某個權值都加上乙個數,設這個權值陣列val,那麼我們需要在val[u],val[v]上加上這個值,並在val[lca(u,v)]上減去這個值,並在val[f[lca(u,v][0]]上減去這個值。
理論如斯。
這個演算法就經常用於統計樹上路徑某點/某邊的經過次數。
例題1
[usaco15dec]最大流max flow(不是網路流題目啦==)
給出若干路徑,求被經過此處最多的點的經過次數。
sol:樹上倍增求lca+樹上差分記錄+最後o(n)掃一遍更新。
總複雜度o(nlogn預處理+klogn求lca+n更新)
1 #include2 #include3 #include4 #include5view code#define maxn 50090067
using
namespace
std;89
intn,k,t,ans,tot;
10int head[maxn],d[maxn],val[maxn],f[maxn][20
];11
struct
nodeedge[maxn*2
];14
15void add(int x,int
y)16
2122
void
init_lca()
2341}42
}4344int lca(int x,int
y)45
5455
void review(int u,int
fa)56
64 ans=max(ans,val[u]);65}
6667
intmain()
6877
init_lca();
78while(k--)
7987 review(1,0
);88 printf("%d"
,ans);
89return0;
90 }
例題2[jloi2014]松鼠的新家
也是求點經過次數的=w=,稍有變動,需要在最後從第2個到達點到最後乙個到達點的權值都減。(題意使然)
1 #include2 #include3 #include4 #include5view code#define maxn 30009067
using
namespace
std;89
intn,tot,t;
10int seq[maxn],head[maxn],val[maxn],d[maxn],f[maxn][20
];11
struct
nodeedge[maxn*2
];14
15void add(int x,int
y)16
2122
void
lca_prework()
2339
} 40}41
42int lca(int x,int
y)43
5253
void review(int u,int
fa)5462}
6364
intmain()
6575
lca_prework();
76for(int i=1;i<=n-1;i++)
7782 review(1,0
);83
for(int i=2;i<=n;i++) val[seq[i]]--;
84for(int i=1;i<=n;i++) printf("
%d\n
",val[i]);
85return0;
86 }
(話說省選出板子題真的好麼==)
2: 邊權:
給你一棵樹,有n次修改操作,每次把u..v的路徑權值加x,最後問從x..y的路徑權值和。上面的話引用自@sagittariusdalao。例如有一次操作是把紅點(u)到綠點(v)之間的路徑全部加x。那麼我就標記dlt[u]+=x,dlt[v]+=x。然後我們要在lca(u,v)處標記dlt[lca(u,v)]-=2x。這樣就使得加x的效果只侷限在u..v,不會向lca(u,v)的爸爸蔓延。
例題:noip2015運輸計畫
val[x]就是x與它的父節點之間的「樹邊」被覆蓋的次數
鏈結中有詳細的題解==
樹上差分的整理(點的樹上差分和邊的樹上差分)
點的樹上差分 若經過 u 到 v 的所有點,tmp u tmp v tmp lca u,v tmp parent lca u,v 0 例題 include using namespace std struct ss ss data 600010 int n,q int a 300010 head 6...
差分 樹上差分略解
差分 樹上差分略解 哈哈差分?先來看一道題 題目描述 給定包含 n個數的陣列 a1,a2,an.有 k次操作 每次操作把區間 l,r 加上v 最後求出數列每個位置的數。輸入格式 第一行,n.第二行,a1,a2,an下一行,k,下k行,每行乙個操作,格式為l,r,v 輸出格式 一行,更新後的陣列 樣例...
差分總結二 樹上差分
找這個樹上 重複經過的最多點 經過幾次 看這名字 就醉了orz 這題是 樹上差分 模板題 點差分 點差分的話 由於 lca 本身是有貢獻的 那麼d lca 用d lca父親 只要消掉影響 include using namespace std const int maxn 1e5 10 int n,...