Ancient Distance(妙啊!!!) [2020牛客暑期多校训练营(第四场)]
Ancient Distance
給定一顆根為111有nnn個(gè)節(jié)點(diǎn)的樹,每次可以選定樹上kkk節(jié)點(diǎn)當(dāng)作特殊節(jié)點(diǎn),
定義dis(u)dis(u)dis(u)為,從u?>1u->1u?>1遇上的第一個(gè)特殊點(diǎn)的距離,如果遇不上特殊點(diǎn)則dis(u)dis(u)dis(u)無窮大。
有nnn次詢問,問,每次選k∈{1,2,3,…,n?1,n}k \in \{1, 2, 3, \dots, n - 1, n\}k∈{1,2,3,…,n?1,n}個(gè)特殊點(diǎn)時(shí)的答案,
有一個(gè)性質(zhì),最大答案為n?1n - 1n?1,且111號(hào)點(diǎn)是一定要選的,接下來考慮其他的點(diǎn)如何選取,
假設(shè)我們當(dāng)前答案為xxx,我們需要選取多少個(gè)點(diǎn),有一個(gè)貪心的想法,找到一個(gè)節(jié)點(diǎn)最深的節(jié)點(diǎn),然后把他的第xxx代祖先設(shè)置為特殊點(diǎn),
這樣我們就保證了這一子樹都滿足答案小于等于xxx,按照這樣依次操作,最后我們的答案都會(huì)小于xxx,
不難發(fā)現(xiàn)對于每個(gè)xxx,我們所需執(zhí)行的操作最多不會(huì)超過?nx?\lceil \frac{n}{x} \rceil?xn??,我們可以利用線段樹來查詢每次需要操作的點(diǎn),這樣保證了一次操作是log?n\log nlogn的,
由此我們發(fā)現(xiàn)整體復(fù)雜度是∑i=1n?ni?log?n=O(nlog?nlog?n)\sum\limits_{i = 1} ^{n} \lceil \frac{n}{i} \rceil \log n = O(n \log n \log n)i=1∑n??in??logn=O(nlognlogn)的。
#include <bits/stdc++.h> #define mid (l + r >> 1) #define lson rt << 1, l, mid #define rson rt << 1 | 1, mid + 1, r #define ls rt << 1 #define rs rt << 1 | 1using namespace std;const int N = 2e5 + 10;int maxn[N << 2], id[N << 2], cov[N << 2], ans[N], n;int l[N], r[N], rk[N], fa[N][21], dep[N], tot;vector<int> G[N];void dfs(int rt, int f) {l[rt] = ++tot, rk[tot] = rt, fa[rt][0] = f, dep[rt] = dep[f] + 1;for (int i = 1; i <= 20; i++) {fa[rt][i] = fa[fa[rt][i - 1]][i - 1];}for (int &to : G[rt]) {if (to == f) {continue;}dfs(to, rt);}r[rt] = tot; }int k_fa(int rt, int k) {for (int i = 20; i >= 0; i--) {if (k >> i & 1) {rt = fa[rt][i];}}return rt; }void push_up(int rt) {maxn[rt] = 0;if (!cov[ls] && maxn[ls] > maxn[rt]) {maxn[rt] = maxn[ls];id[rt] = id[ls];}if (!cov[rs] && maxn[rs] > maxn[rt]) {maxn[rt] = maxn[rs];id[rt] = id[rs];} }void build(int rt, int l, int r) {cov[rt] = 0;if (l == r) {maxn[rt] = dep[rk[l]];id[rt] = rk[l];return ;}build(lson);build(rson);push_up(rt); }void update(int rt, int l, int r, int L, int R, int v) {if (l >= L && r <= R) {cov[rt] = v;return ;}if (L <= mid) {update(lson, L, R, v);}if (R > mid) {update(rson, L, R, v);}push_up(rt); }int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);while (scanf("%d", &n) != EOF) {tot = 0;for (int i = 1; i <= n; i++) {G[i].clear();}for (int i = 2, x; i <= n; i++) {scanf("%d", &x);G[x].push_back(i);G[i].push_back(x);}dep[0] = -1;dfs(1, 0);build(1, 1, n);for (int i = 1; i <= n; i++) {ans[i] = n;}vector<int> vt;for (int cur = n - 1; cur >= 0; cur--) {int num = 1;vt.clear();while (true) {if (maxn[1] <= cur) {break;}num++;int u = k_fa(id[1], cur);vt.push_back(u);update(1, 1, n, l[u], r[u], 1);}ans[num] = cur;for (auto rt : vt) {update(1, 1, n, l[rt], r[rt], 0);}}for (int i = 2; i <= n; i++) {ans[i] = min(ans[i], ans[i - 1]);}long long res = 0;for (int i = 1; i <= n; i++) {res += ans[i];}printf("%lld\n", res);}return 0; }總結(jié)
以上是生活随笔為你收集整理的Ancient Distance(妙啊!!!) [2020牛客暑期多校训练营(第四场)]的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WiFi联盟 /SD卡组织移除华为名单?
- 下一篇: P4175 [CTSC2008]网络管理