QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#65466 | #4839. Smaller LCA | YaoBIG | WA | 1240ms | 55916kb | C++17 | 6.5kb | 2022-12-01 09:37:37 | 2022-12-01 09:37:38 |
Judging History
answer
#include "bits/stdc++.h"
#define rep(i, a, n) for (auto i = a; i <= (n); ++i)
#define revrep(i, a, n) for (auto i = n; i >= (a); --i)
#define all(a) a.begin(), a.end()
#define sz(a) (int)(a).size()
template<class T> inline bool chmax(T &a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T &a, T b) { if (b < a) { a = b; return 1; } return 0; }
using namespace std;
template<class A, class B> string to_string(const pair<A, B> &p);
string to_string(const string &s) { return '"' + s + '"'; }
string to_string(const char *s) { return to_string((string) s); }
string to_string(char c) { return "'" + string(1, c) + "'"; }
string to_string(bool x) { return x ? "true" : "false"; }
template<class A> string to_string(const A &v) {
bool first = 1;
string res = "{";
for (const auto &x: v) {
if (!first) res += ", ";
first = 0;
res += to_string(x);
}
res += "}";
return res;
}
template<class A, class B> string to_string(const pair<A, B> &p) {
return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}
void debug_out() { cerr << endl; }
template<class H, class... T> void debug_out(const H& h, const T&... t) {
cerr << " " << to_string(h);
debug_out(t...);
}
#ifndef ONLINE_JUDGE
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) if(0) puts("No effect.")
#endif
using ll = long long;
using pii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;
/**
* Author: Yuhao Yao
* Date: 22-10-25
* Description: Heavy Light Decomposition for a rooted tree $T$. The root is set as $0$ by default. It can be modified easily for forest.
* $g$ should be the adjacent list of the tree $T$.
* $chainApply(u, v, func, val)$ and $chainAsk(u, v, func)$ are used for apply / query on the simple path from $u$ to $v$ on tree $T$. $func$ is the function you want to use to apply / query on a interval. (Say rangeApply / rangeAsk of Segment tree.)
* Time: O(|T|) for building. O(\log |T|) for lca. O(\log |T| \cdot A) for chainApply / chainAsk, where $A$ is the running time of $func$ in chainApply / chainAsk.
* Status: tested on https://codeforces.com/contest/487/problem/E.
*/
struct HLD {
int n; /// start-hash
vi fa, hson, dfn, dep, top;
HLD(vector<vi> &g, int rt = 0): n(sz(g)), fa(n, -1), hson(n, -1), dfn(n), dep(n, 0), top(n) {
vi siz(n);
auto dfs = [&](auto &dfs, int now) -> void {
siz[now] = 1;
int mx = 0;
for (auto v: g[now]) if (v != fa[now]) {
dep[v] = dep[now] + 1;
fa[v] = now;
dfs(dfs, v);
siz[now] += siz[v];
if (mx < siz[v]) {
mx = siz[v];
hson[now] = v;
}
}
};
dfs(dfs, rt);
int cnt = 0;
auto getdfn = [&](auto &dfs, int now, int sp) {
top[now] = sp;
dfn[now] = cnt++;
if (hson[now] == -1) return;
dfs(dfs, hson[now], sp);
for (auto v: g[now]) {
if(v != hson[now] && v != fa[now]) dfs(dfs, v, v);
}
};
getdfn(getdfn, rt, rt);
} /// end-hash
int lca(int u, int v) { /// start-hash
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
u = fa[top[u]];
}
if (dep[u] < dep[v]) return u;
else return v;
} /// end-hash
template<class... T> /// start-hash
void chainApply(int u, int v, const function<void(int, int, T...)> &func, const T&... val) {
int f1 = top[u], f2 = top[v];
while (f1 != f2) {
if (dep[f1] < dep[f2]) swap(f1, f2), swap(u, v);
func(dfn[f1], dfn[u], val...);
u = fa[f1]; f1 = top[u];
}
if (dep[u] < dep[v]) swap(u, v);
func(dfn[v], dfn[u], val...); // change here if you want the info on edges.
} /// end-hash
template<class T> /// start-hash
T chainAsk(int u, int v, const function<T(int, int)> &func) {
int f1 = top[u], f2 = top[v];
T ans{};
while (f1 != f2) {
if (dep[f1] < dep[f2]) swap(f1, f2), swap(u, v);
ans = ans + func(dfn[f1], dfn[u]);
u = fa[f1]; f1 = top[u];
}
if (dep[u] < dep[v]) swap(u, v);
ans = ans + func(dfn[v], dfn[u]); // change here if you want the info on edges.
return ans;
} /// end-hash
};
/**
* Author: Yuhao Yao
* Date: 22-09-27
* Description: Fenwick Tree.
*/
template<class T> struct BIT {
int n;
vector<T> a;
BIT(int n): n(n), a(n + 1, 0) {}
void Add(int i, T x) {
for (++i; i <= n; i += i & -i) a[i] += x;
}
T Ask(int i) {
T ans{};
for (++i; i; i -= i & -i) ans += a[i];
return ans;
}
T rangeAsk(int l, int r) { return Ask(r) - Ask(l - 1); }
// assuming prefix sums are non-decreasing, finds the first pos such that ask(pos) >= x.
int lower_bound(T x) {
assert(n > 0);
int pos = 0;
for (int h = 1 << __lg(n); h; h >>= 1) {
if ((pos | h) <= n && a[pos | h] < x) {
pos |= h;
x -= a[pos];
}
}
return pos;
}
};
int main() {
ios::sync_with_stdio(0); cin.tie(0);
int n; cin >> n;
vvi g(n);
rep(i, 1, n - 1) {
int x, y; cin >> x >> y;
x--; y--;
g[x].push_back(y);
g[y].push_back(x);
}
HLD hld(g);
auto fa = hld.fa;
auto tin = hld.dfn;
vi tout(n);
auto getdfn = [&](auto &dfs, int now, int fa) -> void {
tout[now] = tin[now];
for (auto v: g[now]) if (v != fa) {
dfs(dfs, v, now);
chmax(tout[now], tout[v]);
}
};
getdfn(getdfn, 0, -1);
vector<pii> pairs;
rep(x, 1, n) rep(y, x, n) {
if (1ll * x * y > n) break;
pairs.emplace_back(x, y);
}
sort(all(pairs), [](pii a, pii b) { return 1ll * a.first * a.second < 1ll * b.first * b.second; });
BIT<ll> bit(n), bit2(n);
auto ptr = pairs.begin();
vector<ll> tag(n), tag1(n), tag2(n);
rep(z, 1, n) {
int now = z - 1;
while (ptr != pairs.end() && 1ll * ptr->first * ptr->second < z) {
auto [x, y] = *ptr;
ptr++;
int u = x - 1;
int v = y - 1;
int lca = hld.lca(u, v);
if (lca + 1 > 1ll * x * y) {
tag2[lca]++;
}
bit.Add(tin[u], 1);
bit.Add(tin[v], 1);
bit.Add(tin[lca], -1);
if (fa[lca] != -1) bit.Add(fa[lca], -1);
bit2.Add(tin[u], 1);
bit2.Add(tin[v], 1);
bit2.Add(tin[lca], -2);
}
tag[now] = bit.rangeAsk(tin[now], tout[now]);
for (auto v: g[now]) if (v != fa[now]) {
tag1[v] += tag[now] - bit2.rangeAsk(tin[v], tout[v]);
}
}
ll tot = accumulate(all(tag2), 0ll);
auto dfs = [&](auto &dfs, int now, int fa) -> void {
for (auto v: g[now]) if (v != fa) {
tag1[v] += tag1[now];
tag2[v] += tag2[now];
dfs(dfs, v, now);
}
};
dfs(dfs, 0, -1);
rep(now, 0, n - 1) {
ll ans = 1ll * n * (n + 1) / 2 - (tag[now] + tag1[now] + tot - tag2[now]);
printf("%lld\n", ans);
}
return 0;
}
詳細信息
Test #1:
score: 100
Accepted
time: 1ms
memory: 3648kb
input:
5 1 2 4 2 2 5 3 5
output:
15 15 15 15 14
result:
ok 5 number(s): "15 15 15 15 14"
Test #2:
score: -100
Wrong Answer
time: 1240ms
memory: 55916kb
input:
300000 40632 143306 32259 40632 225153 143306 269774 225153 289668 40632 191636 269774 85717 191636 58564 191636 156509 143306 289939 40632 247103 269774 40257 40632 98149 289668 142277 143306 291616 40257 46813 225153 56324 143306 277154 142277 53903 289668 114266 32259 152231 58564 241151 152231 4...
output:
44999437117 45000307324 45000331953 45000330914 44999549684 45000347970 44999874404 44999614805 44999580521 44999620598 45000317665 44999627843 44999760068 44999428454 45003764953 44999937804 44999612042 44999794083 44999804849 44999616318 45000255363 44999854065 44999950322 44999611884 44999414103 ...
result:
wrong answer 2nd numbers differ - expected: '44999604051', found: '45000307324'