Brief description:
给定一棵 n 个结点的树,叶节点有一个权值,问以每个内结点为根的子树,所有叶节点之间权值差最小的值。
( n <= 50000 )
Analysis:
… . 启发式合并。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | const int N = 50009; SI S[N]; queue< int > Q; int p[N], c[N], h[N], res[N], n, m; int main(){ //freopen("in.txt", "r", stdin); RD(n, m); fill(res, res + n, 0x7fffffff); FOR(i, 1, n) ++c[--_RD(p[i])]; REP(i, n) h[i] = i; FOR(i, n - m, n) S[i].insert(RD()), Q.push(i); while (!Q.empty()){ int u = Q.front(); Q.pop(); #define uu h[u] #define v p[u] #define vv h[v] if (SZ(S[vv]) < SZ(S[uu])) swap(uu, vv); if (S[vv].empty()){ res[v] = res[u]; vv = uu; } else { checkMin(res[v], res[u]); /* SI::iterator jt, kt; pair<SI::iterator, bool> tmp; ECH(it, S[uu]){ tmp = S[vv].insert(*it); if (!tmp.second) {res[v] = 0; break;} else { jt = tmp.first; if (jt != S[vv].begin()) kt = jt, --kt, checkMin(res[v], *jt - *kt); kt = jt; ++kt; if (kt != S[vv].end()) checkMin(res[v], *kt - *jt); } } */ SI::iterator jt; ECH(it, S[uu]){ SI::iterator jt = S[vv].lower_bound(*it); if (jt != S[vv].end()) res[v] = min(res[v], *jt - *it); if (jt != S[vv].begin()) res[v] = min(res[v], *it - *--jt); if (!res[v]) break ; } if (res[v]) ECH(it, S[uu]) S[vv].insert(*it); } if (!--c[v] && v) Q.push(v); } REP(i, n - m) cout << res[i] << " " ; cout << endl; } |