QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#65463 | #4839. Smaller LCA | YaoBIG | WA | 1135ms | 55972kb | C++17 | 6.5kb | 2022-12-01 09:23:38 | 2022-12-01 09:23: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 > 1ll * x * y && fa[lca] != -1) {
tag2[fa[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]);
}
}
auto dfs = [&](auto &dfs, int now, int fa) -> void {
for (auto v: g[now]) if (v != fa) {
tag1[v] += tag1[now];
dfs(dfs, v, now);
tag2[now] += tag2[v];
}
};
dfs(dfs, 0, -1);
rep(now, 0, n - 1) {
ll ans = 1ll * n * (n + 1) / 2 - (tag[now] + tag1[now] + tag2[now]);
printf("%lld\n", ans);
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 3ms
memory: 3752kb
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: 1135ms
memory: 55972kb
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:
44999437122 45000545415 45000566485 45000565448 44999667417 45000577680 44999969267 44999718497 44999696092 44999691885 45000553851 44999699060 44999849308 45000078550 45003991392 45000201213 44999684688 44999887062 44999897989 44999689002 45000494837 44999946874 45000213704 44999715770 45000084850 ...
result:
wrong answer 1st numbers differ - expected: '44999437117', found: '44999437122'