解決樹上統計問題,o(n
∗log
(n))
o(n*log(n))
o(n∗lo
g(n)
),可以結合線段樹等資料結構維護深度上的資訊
部落格
入門題
const
int maxn =
1e5+7;
const
int mod =
1e9+7;
ll n, m, u, v, mx, sum;
vector<
int> mp[maxn]
;int sz[maxn]
, son[maxn]
;void
dfs(
int u,
int fa)
}ll col[maxn]
, cnt[maxn]
, ans[maxn]
, flag;
void
count
(int u,
int fa)
else
if(cnt[col[u]
]== mx)
sum +
= col[u]
;for
(auto v : mp[u])}
void
clear
(int u,
int fa)
}voiddf(
int u,
int fa,
bool kp)
if(son[u]
)count
(u, fa)
; flag =
0, ans[u]
= sum;if(
!kp)
}int
main()
dfs(1,
0);df
(1,0
,1);
for(
int i =
1; i <= n; i++
) cout << ans[i]
<<
" ";
return0;
}
結合線段樹維護深度上的最值
#define mid ((tr[k].l + tr[k].r) >> 1)
#define ls k << 1
#define rs k << 1 | 1
const
int maxn =
1e5+7;
const
int mod =
1e9+7;
int n, t, flag, mxdep;
int sz[maxn]
, son[maxn]
, dep[maxn]
, val[maxn]
;ll sum[maxn]
, ans[maxn]
;vector<
int> mp[maxn]
;void
dfs(
int u,
int dp)
}struct node tr[maxn <<2]
;void
build
(int k,
int l,
int r)
build
(k <<
1, l, mid)
,build
(k <<1|
1, mid +
1, r)
; tr[k]
.w =
max(tr[k <<1]
.w, tr[k <<1|
1].w);
}void
change
(int k,
int pl,
int x)
if(pl <= mid)
change
(k <<
1, pl, x)
;else
change
(k <<1|
1, pl, x)
; tr[k]
.w =
max(tr[k <<1]
.w, tr[k <<1|
1].w);
}ll query()
void
init()
for(
int i =
0; i <= n *
4; i++
) tr[i]
.l = tr[i]
.r = tr[i]
.w =0;
}void
count
(int u)
void
clear
(int u)
voiddf(
int u,
int kep)
if(son[u]
)count
(u);
ans[u]
=query()
;if(!kep)
}int
main()
dfs(1,
1);build(1
,1, mxdep);df
(1,1
);for(
int i =
2; i <= n; i++
) cout << ans[i]
<<
"\n";}
return0;
}
按層維護26個字母的數量
const
int maxn =
5e5+7;
const
int mod =
1e9+7;
int n, q, t, flag, mxdep;
int sz[maxn]
, son[maxn]
, dep[maxn]
, ques[2]
[maxn]
;char val[maxn]
;vector<
int> mp[maxn]
, que[maxn]
;int cnt[maxn][40
];mapint> ans;
void
dfs(
int u,
int dp)
}void
count
(int u)
void
clear
(int u)
bool
check
(int dp)
voiddf(
int u,
int kep)
if(son[u]
)count
(u);
for(
auto d : que[u]
) ans=
check
(d);if(
!kep)
}int
main()
cin >> val +1;
dfs(1,
1);for
(int i =
1, a, b; i <= q; i++)df
(1,1
);for(
int i =
1; i <= q; i++)]
) cout <<
"yes"
<< endl;
else
cout <<
"no"
<< endl;
}return0;
}
樹上啟發式合併
樹上啟發式合併,一種美妙的黑科技,可以用普通的優化讓你 n 2 變成嚴格 n log 解決一些類似 樹上數顏色,樹上查眾數 這樣的問題 首先你要知道暴力為什麼是 n 2 的 以這個圖為例 每次你從乙個節點開始向下搜,你從1節點搜到3,搜完這個子樹然後你需要把3存的col等資訊刪去再遍歷另乙個子樹才是...
樹上啟發式合併總結
某一天發現一道樹上啟發式合併裸題,但我不會寫 學習並刷了兩天的題,是時候來寫個總結了 樹上啟發式合併 dsu on tree 是乙個在o n logn o nlogn o nlog n 時間內解決許多樹上問題的有力演算法。但它的中心其實是 暴力!沒錯,它正是由暴力優化而來。我們先看一道例題 cf60...
dsu on tree 樹上啟發式合併
詳解 dsu on tree 樹上啟發式合併 演算法總結 習題 經典例題 題意 一棵樹有n個結點,每個結點都是一種顏色,每個顏色有乙個編號,求樹中每個子樹的最多的顏色編號的和。dsu on tree簡介 在o n 2 的暴力做法中,我們用cnt記錄每種顏色出現的次數,對於每個結點,遍歷這棵子樹上的所...