제출 #1266857

#제출 시각아이디문제언어결과실행 시간메모리
1266857faricaHarbingers (CEOI09_harbingers)C++20
100 / 100
133 ms20644 KiB
#include<bits/stdc++.h> using namespace std; using vi = vector<int>; using pi = pair<int,int>; typedef long long ll; #define debug(x) cout << #x << " = " << x << "\n"; #define vdebug(a) cout << #a << " = "; for(auto x: a) cout << x << " "; cout << "\n"; const int MOD = 1e9 + 7; const int INF = 1e9; template<ll mod> struct modnum { static constexpr bool is_big_mod = mod > numeric_limits<int>::max(); using S = conditional_t<is_big_mod, ll, int>; using L = conditional_t<is_big_mod, __int128, ll>; S x; modnum() : x(0) {} modnum(ll _x) { _x %= static_cast<ll>(mod); if (_x < 0) { _x += mod; } x = _x; } modnum pow(ll n) const { modnum res = 1; modnum cur = *this; while (n > 0) { if (n & 1) res *= cur; cur *= cur; n /= 2; } return res; } modnum inv() const { return (*this).pow(mod-2); } modnum& operator+=(const modnum& a){ x += a.x; if (x >= mod) x -= mod; return *this; } modnum& operator-=(const modnum& a){ if (x < a.x) x += mod; x -= a.x; return *this; } modnum& operator*=(const modnum& a){ x = static_cast<L>(x) * a.x % mod; return *this; } modnum& operator/=(const modnum& a){ return *this *= a.inv(); } friend modnum operator+(const modnum& a, const modnum& b){ return modnum(a) += b; } friend modnum operator-(const modnum& a, const modnum& b){ return modnum(a) -= b; } friend modnum operator*(const modnum& a, const modnum& b){ return modnum(a) *= b; } friend modnum operator/(const modnum& a, const modnum& b){ return modnum(a) /= b; } friend bool operator==(const modnum& a, const modnum& b){ return a.x == b.x; } friend bool operator!=(const modnum& a, const modnum& b){ return a.x != b.x; } friend bool operator<(const modnum& a, const modnum& b){ return a.x < b.x; } friend ostream& operator<<(ostream& os, const modnum& a){ os << a.x; return os; } friend istream& operator>>(istream& is, modnum& a) { ll x; is >> x; a = modnum(x); return is; } }; using mint = modnum<MOD>; template <class T> class SumSegmentTree { private: const T DEFAULT = 0; vector<T> segtree; int len; public: SumSegmentTree(int len) : len(len), segtree(len * 2, DEFAULT) {} void set(int ind, T val) { ind += len; segtree[ind] = val; for (; ind > 1; ind /= 2) { segtree[ind / 2] = segtree[ind] + segtree[ind ^ 1]; } } T range_sum(int start, int end) { T sum = DEFAULT; for (start += len, end += len; start < end; start /= 2, end /= 2) { if (start % 2 == 1) { sum += segtree[start++]; } if (end % 2 == 1) { sum += segtree[--end]; } } return sum; } }; /* const int N = 250005; struct BIT { ll b[N], n; void init(int _n) { n = _n ; for(int i = 0 ; i <= n ; ++i) b[i] = 0; } inline int lowbit(int x) { return x & (-x); } void update(int x, ll v) { for(int i = x ; i <= n ; i += lowbit(i)) b[i] += v; } ll query(int x) { ll ans = 0; for(int i = x ; i > 0 ; i -= lowbit(i)) ans += b[i]; return ans; } } bit[2]; */ int gcd(int a, int b, int& x, int& y) { // x*a + y*b = a1 x = 1, y = 0; int x1 = 0, y1 = 1, a1 = a, b1 = b; while (b1) { int q = a1 / b1; tie(x, x1) = make_tuple(x1, x - q * x1); tie(y, y1) = make_tuple(y1, y - q * y1); tie(a1, b1) = make_tuple(b1, a1 - q * b1); } return a1; } int inv_ecd(int a, int m) { int x, y; int g = gcd(a, m, x, y); if(g != 1) return -1; x = (x + m) % m; return x; } const int maxn = 1e5 + 1; using ld = long double; struct Line { ll m, b; Line(ll m = 0, ll b = 0) : m(m), b(b) {} ll operator()(ll x) { return m * x + b; } friend ld intersect(Line l1, Line l2) { return (ld)(l2.b - l1.b) / (ld)(l1.m - l2.m); } }; int n, siz; Line stk[maxn]; vector<pi>adjL[maxn]; vi v, s; vector<ll>ans; int remove_pos(Line line) { if(siz < 2 or intersect(line, stk[siz-1]) >= intersect(stk[siz-1], stk[siz-2])) return siz; int l=1, r=siz-1; while(l<r) { int m = (l+r)/2; if(intersect(line, stk[m]) < intersect(stk[m], stk[m-1])) r=m; else l=m+1; } return l; } ll get_min(ll x) { int l=0, r=siz-1; while(l<r) { int m = (l+r)/2; if(intersect(stk[m], stk[m+1]) < x) l = m+1; else r = m; } return stk[l](x); } void dfs(int pos, ll d, int prev=0) { int prev_siz, prev_pos; Line prev_line; if(!pos) { ans[pos] = 0; stk[siz++] = {0,0}; } else { ans[pos] = get_min(v[pos]) + 1LL * d * v[pos] + s[pos]; Line tmp(-d, ans[pos]); prev_siz = siz; prev_pos = siz = remove_pos(tmp); prev_line = stk[siz]; stk[siz++] = tmp; } for(auto [V,W]: adjL[pos]) { if(V == prev) continue; dfs(V, d+W, pos); } if(pos) { siz = prev_siz; stk[prev_pos] = prev_line; } } void solve() { cin >> n; v.resize(n); s.resize(n); ans.resize(n); for(int i=0; i<n-1; ++i) { int u,v,d; cin >> u >> v >> d; --u, --v; adjL[u].push_back({v,d}); adjL[v].push_back({u,d}); } for(int i=1; i<n; ++i) cin >> s[i] >> v[i]; dfs(0, 0); for(int i=1; i<n; ++i) cout << ans[i] << endl; } int main(){ ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); //freopen("strange_file.txt", "r", stdin); //freopen("strange_file3.txt", "w", stdout); int tc = 1; while (tc--) solve(); }
#Verdict Execution timeMemoryGrader output
Fetching results...