Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- using ll = long long;
- using ld = long double;
- constexpr int N = 1e5 + 2;
- constexpr ll Inf = 1e17;
- int n, cnt[N], chain[N], in[N], rev[N], l, m;
- int id[N], par[N], beg[N], en[N];
- ll a[N], b[N], dp[N];
- struct ConvexHullTrick
- {
- vector<int> line, tre;
- vector<ld> point;
- bool build;
- ConvexHullTrick()
- {
- point.emplace_back(-Inf);
- build = false;
- }
- void AddEdge(int v)
- {
- tre.emplace_back(v);
- }
- ld f(int x, int y)
- {
- return (ld)1.0 * (dp[x] - dp[y]) / (b[y] - b[x]);
- }
- void AddLine(int i)
- {
- while (line.size() > 1 || (line.size() == 1 && b[line.back()] == b[i] && dp[line.back()] > dp[i]))
- {
- if (b[line.back()] != b[i])
- {
- if (f(i, line[line.size() - 2]) >= f(i, line.back()))
- {
- line.pop_back();
- if (!line.empty())
- point.pop_back();
- }
- else
- break;
- }
- else
- {
- if (dp[i] < dp[line.back()])
- {
- line.pop_back();
- if (!line.empty())
- point.pop_back();
- }
- else
- break;
- }
- }
- if (line.empty() || b[i] != b[line.back()])
- {
- if (!line.empty())
- point.emplace_back(f(i, line.back()));
- line.emplace_back(i);
- }
- }
- void construct()
- {
- for (auto i : tre)
- AddLine(i);
- build = 1;
- }
- ll Get(const ll &r)
- {
- if (line.empty())
- return Inf;
- int j = lower_bound(point.begin(), point.end(), r) - point.begin() - 1;
- return b[line[j]] * r + dp[line[j]];
- }
- };
- struct SegmentTree
- {
- ConvexHullTrick st[N * 4];
- void Update(int id, int l, int r, const int &a, const int &b, const int &v)
- {
- if (l > b || r < a)
- return;
- if (l >= a && r <= b)
- {
- st[id].AddEdge(v);
- return;
- }
- Update(id << 1, l, (l + r) / 2, a, b, v);
- Update(id << 1 | 1, (l + r) / 2 + 1, r, a, b, v);
- }
- void Update(int l, int r, int v)
- {
- Update(1, 1, n, l, r, v);
- //cerr << l << " " << r << " " << v << "\n";
- }
- ll Get(int id, int l, int r, const int &x, const ll &v)
- {
- if (l > x || r < x)
- return Inf;
- if (!st[id].build)
- st[id].construct();
- ll ans = st[id].Get(v);
- if (l == r)
- return ans;
- return min(ans, min(Get(id << 1, l, (l + r) / 2, x, v), Get(id << 1 | 1, (l + r) / 2 + 1, r, x, v)));
- }
- ll Get(int id)
- {
- return Get(1, 1, n, id, a[rev[id]]);
- }
- } f;
- vector<int> adj[N];
- void Read()
- {
- cin >> n;
- for (int i = 1; i <= n; ++i)
- cin >> a[id[i] = i];
- for (int i = 1; i <= n; ++i)
- cin >> b[i];
- for (int i = 1; i < n; ++i)
- {
- int u, v;
- cin >> u >> v;
- adj[u].emplace_back(v);
- adj[v].emplace_back(u);
- }
- }
- void dfs(int v, int p = 0)
- {
- par[v] = p;
- cnt[v] = 1;
- for (int i = adj[v].size() - 1; ~i; --i)
- if (adj[v][i] == p)
- {
- adj[v][i] = adj[v].back();
- adj[v].pop_back();
- }
- else
- {
- dfs(adj[v][i], v);
- cnt[v] += cnt[adj[v][i]];
- }
- }
- void hld(int v)
- {
- //cerr << v << " ";
- chain[v] = m;
- in[v] = ++l;
- rev[in[v]] = v;
- if (!beg[m])
- beg[m] = in[v];
- en[m] = in[v];
- pair<int, int> s = {0, 0};
- for (auto i : adj[v])
- s = max(s, make_pair(cnt[i], i));
- if (s.first)
- hld(s.second);
- for (auto i : adj[v])
- if (i != s.second)
- {
- ++m;
- hld(i);
- }
- }
- void Update(int x)
- {
- int v = x;
- x = par[x];
- while (x)
- {
- f.Update(beg[chain[x]], in[x], v);
- x = par[rev[beg[chain[x]]]];
- }
- }
- void Solve()
- {
- dfs(1);
- m = 1;
- hld(1);
- //cerr << "\n";
- sort(id + 1, id + n + 1, [&](const int &x, const int &y)
- { return b[x] > b[y] || (b[x] == b[y] && in[x] < in[y]); });
- for (int i = 1; i <= n; ++i)
- Update(id[i]);
- for (int i = n; i; --i)
- dp[rev[i]] = adj[rev[i]].empty() ? 0 : f.Get(i);
- for (int i = 1; i <= n; ++i)
- cout << dp[i] << " ";
- }
- int32_t main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- Read();
- Solve();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement