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 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
| #include <bits/stdc++.h> using namespace std; template <typename T1, typename T2> istream &operator>>(istream &is, pair<T1, T2> &pa) { is >> pa.first >> pa.second; return is; } template <typename T> istream &operator>>(istream &is, vector<T> &vec) { for (auto &v : vec) is >> v; return is; } template <typename T1, typename T2> ostream &operator<<(ostream &os, const pair<T1, T2> &pa) { os << "(" << pa.first << "," << pa.second << ")"; return os; } template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) { os << "["; for (auto v : vec) os << v << ","; os << "]"; return os; } template <typename T> ostream &operator<<(ostream &os, const deque<T> &vec) { os << "deq["; for (auto v : vec) os << v << ","; os << "]"; return os; } template <typename T> ostream &operator<<(ostream &os, const set<T> &vec) { os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; } template <typename T> ostream &operator<<(ostream &os, const multiset<T> &vec) { os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; } template <typename T> ostream &operator<<(ostream &os, const unordered_set<T> &vec) { os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; } template <typename T> ostream &operator<<(ostream &os, const unordered_multiset<T> &vec) { os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; } template <typename TK, typename TV> ostream &operator<<(ostream &os, const unordered_map<TK, TV> &mp) { os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; } template <typename TK, typename TV> ostream &operator<<(ostream &os, const map<TK, TV> &mp) { os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; } template <typename T> void resize_array(vector<T> &vec, int len) { vec.resize(len); } template <typename T, typename... Args> void resize_array(vector<T> &vec, int len, Args... args) { vec.resize(len); for (auto &v : vec) resize_array(v, args...); } template <typename T1, typename T2> pair<T1, T2> operator+(const pair<T1, T2> &l, const pair<T1, T2> &r) { return make_pair(l.first + r.first, l.second + r.second); } template <typename T1, typename T2> pair<T1, T2> operator-(const pair<T1, T2> &l, const pair<T1, T2> &r) { return make_pair(l.first - r.first, l.second - r.second); } long long gcd(long long a, long long b) { return b ? gcd(b, a % b) : a; } mt19937 mrand(random_device{}()); int rnd(int x) { return mrand() % x; } #define rep(i, a, n) for (int i = a; i < (n); i++) #define per(i, a, n) for (int i = (n)-1; i >= a; i--) #define pb push_back #define mp make_pair #define all(x) (x).begin(), (x).end() #define fi first #define se second #define sz(x) ((int)(x).size()) typedef vector<int> vi; typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; typedef pair<int, int> pii; typedef double db; #if DEBUG #define dbg(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ") " << __FILE__ << endl; #else #define dbg(x) #endif
template<typename T> struct Line { T k, b; mutable T intersect_x; bool operator<(const Line<T>& o) const { return k < o.k; } bool operator<(T x) const { return intersect_x < x; } T Eval(T x) const { return k * x + b; } T IntersectX(const Line<T>& line) const { assert(k != line.k); return Div(line.b - b, k - line.k); } T Div(T a, T b) const { if constexpr (std::is_integral<T>::value) { return a / b - ((a ^ b) < 0 && a % b); } else { return a / b; } } };
template <typename T, int FIND_MIN = 0> class LineContainer { public: void Add(T k, T b) { if (FIND_MIN) Add(Line<T>{-k, -b, 0}); else Add(Line<T>{k, b, 0}); } T Query(T x) { assert(!lines.empty()); auto it = lines.begin(); auto l = lines.lower_bound(x); return FIND_MIN ? -(l->Eval(x)) : l->Eval(x); } size_t Size() { return lines.size(); } void Swap(LineContainer<T, FIND_MIN>& other) { lines.swap(other.lines); } void Merge(const LineContainer<T, FIND_MIN>& other) { for (auto line : other.lines) { Add(line); } } private: void Add(const Line<T>& line) { auto nxt = lines.insert(line), cur = nxt++, prev = cur; while (Intersect(cur, nxt)) nxt = lines.erase(nxt); if (prev != lines.begin() && Intersect(--prev, cur)) Intersect(prev, cur = lines.erase(cur)); while ((cur = prev) != lines.begin() && (--prev)->intersect_x >= cur->intersect_x) Intersect(prev, lines.erase(cur)); } bool Intersect(typename multiset<Line<T>>::iterator l1, typename multiset<Line<T> >::iterator l2) { if (l2 == lines.end()) { l1->intersect_x = numeric_limits<T>::max(); return false; } if (l1->k == l2->k) { l1->intersect_x = l1->b > l2->b ? numeric_limits<T>::max() : numeric_limits<T>::lowest(); } else { l1->intersect_x = l1->IntersectX(*l2); } return l1->intersect_x >= l2->intersect_x; }
multiset<Line<T>, less<>> lines; };
class Solution { public: void Solve() { int n; while(cin>>n) { vi a(n), b(n); cin>>a>>b;
vector<vi> edges(n); int u,v; rep(i,0,n-1) { cin>>u>>v; u--; v--; edges[u].emplace_back(v); edges[v].emplace_back(u); }
vector<ll> dp(n, numeric_limits<ll>::max()); function<void(int, int, LineContainer<ll, 1> &)> dfs = [&](int u, int p, LineContainer<ll, 1> &lines) { if (sz(edges[u]) == 1 && edges[u][0] == p) { dp[u] = 0; } else { for (auto v : edges[u]) { if (v == p) continue; LineContainer<ll, 1> tmp; dfs(v, u, tmp); if (tmp.Size() > lines.Size()) lines.Swap(tmp); lines.Merge(tmp); } dp[u] = lines.Query(a[u]); } lines.Add(b[u], dp[u]); };
LineContainer<ll, 1> lines; dfs(0, -1, lines);
rep(i,0,sz(dp)) { if (i) cout << " "; cout << dp[i]; } cout << endl;
} } private: };
void set_io(const string &name = "") { ios::sync_with_stdio(false); cin.tie(nullptr); #if FILE_IO || USACO if (!name.empty()) { freopen((name + ".in").c_str(), "r", stdin); freopen((name + ".out").c_str(), "w", stdout); } #endif }
int main() { #if USACO set_io("time"); #else set_io("tmp"); #endif Solution().Solve();
return 0; }
|