P3258 [JLOI2014]松鼠的新家
文章目錄
- 題意:
- 題解:
- 樹(shù)上差分
- 代碼:
- 樹(shù)鏈剖分
- 代碼:
P3258 [JLOI2014]松鼠的新家
題意:
n個(gè)點(diǎn),n-1條邊,給出每個(gè)點(diǎn)的拜訪順序,問(wèn)每個(gè)點(diǎn)經(jīng)過(guò)幾次(最后一次移動(dòng)不算拜訪)
題解:
題意明確后就很好做了,對(duì)于給定的x和y,我們只需要分別將x和y到lca(x,y)經(jīng)過(guò)的點(diǎn)加一即可
但是這樣直接做肯定不行
有兩個(gè)方法:
樹(shù)上差分
參考題解
我們先考慮對(duì)于數(shù)組,我們指定連續(xù)一段加一
我們現(xiàn)在對(duì)a2到a6區(qū)間進(jìn)行加一
現(xiàn)在處理差分?jǐn)?shù)組,我們對(duì)a2加一,對(duì)a7減一
差分屬豬的定義:a[i] = a[i-1] + 差分?jǐn)?shù)組[i]
也就是我們并沒(méi)有改變區(qū)間的值,而是改變的兩個(gè)數(shù)之間的相對(duì)大小
對(duì)于樹(shù)上差分:
父親節(jié)點(diǎn)u = 其所有的子節(jié)點(diǎn) + 他本身的差分?jǐn)?shù)組
我們現(xiàn)在改變S到T邊上所有點(diǎn)的值
我們對(duì)S的父親節(jié)點(diǎn)減1,對(duì)T加1
當(dāng)計(jì)算每個(gè)點(diǎn)具體值時(shí):
for(遍歷與 u 相連的每一個(gè)子節(jié)點(diǎn) v){num[u] += num[v]; } num[u] += chafen[u];//加上差分?jǐn)?shù)組
在本題中結(jié)合lca即可
代碼:
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std;const int maxn = 300050; const int maxm = maxn << 1; int N, M; int a[maxn], t1, t2; int head[maxn], cnt;struct Edge{int u, v, next; }edge[maxm];inline void addedge(int u, int v){edge[++cnt].u = u;edge[cnt].v = v;edge[cnt].next = head[u];head[u] = cnt; }int fa[maxn][31], dep[maxn];void dfs(int u, int faa){fa[u][0] = faa, dep[u] = dep[faa] + 1;for(int i = 1; i <= 30; i++){fa[u][i] = fa[ fa[u][i - 1] ][i - 1];}for(int i = head[u]; i ; i = edge[i].next){int v = edge[i].v;if(v == faa)continue;dfs(v, u);} } inline int lca(int x, int y){if(dep[x] < dep[y])swap(x,y);for(int i = 30; i >= 0; i--){if(dep[ fa[x][i] ] >= dep[y]) x = fa[x][i];}if(x == y)return x;for(int i = 30; i >= 0; i--){if(fa[x][i] != fa[y][i]){x = fa[x][i], y = fa[y][i];}}return fa[x][0]; }int num[maxn];int answer(int u, int faa){for(int i = head[u]; i ; i = edge[i].next){int v = edge[i].v;if(v == faa)continue;answer(v, u);num[u] += num[v];} } int main(){cin>>N;for(int i = 1; i <= N; i++){cin>> a[i];}for(int i = 1; i < N; i++){cin>> t1>> t2;addedge(t1, t2);addedge(t2, t1);}dfs(1, 0);for(int i = 1; i <= N - 1; i++){int u = a[i], v = a[i + 1];int t = lca(u, v);num[ fa[t][0] ] -= 1;num[ t ] -= 1;num[ u ] += 1;num[ v ] += 1;}answer(1,0);for(int i = 2; i <= N; i++){num[a[i]]--;}for(int i = 1; i <= N; i++){cout<<num[i]<<endl;} }樹(shù)鏈剖分
樹(shù)鏈剖分就直接進(jìn)行區(qū)間修改加一就行哈
代碼:
這個(gè)代碼我調(diào)了半個(gè)晚上,哭了哭了,終于調(diào)好了
總結(jié)
以上是生活随笔為你收集整理的P3258 [JLOI2014]松鼠的新家的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 晚上睡觉口腔出血是什么原因
- 下一篇: P3178 [HAOI2015]树上操作