Submission #1263362

#TimeUsernameProblemLanguageResultExecution timeMemory
1263362amigoo99234Harbingers (CEOI09_harbingers)C++20
20 / 100
169 ms131072 KiB
#include <bits/stdc++.h>

using namespace std;

//long long MOD = 1e9 + 7;
const long long MOD = 998244353;
// const long long MOD = 100000007 ;


#define fast ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)

#define popCnt(x) (__builtin_popcountll(x))
#define int long long
#define ld long double

#define F  first
#define S  second
#define pi  M_PI
#define all(x) x.begin() , x.end()
#define ll long long
#define SZ(v) (int)(v.size())

int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};
const long long OO = LLONG_MAX / 4, N = 1e9 + 5, M = 1e5 + 5, K = 505;



// A line: y = m * x + c
struct Line {
    ll m, c;
    Line(ll _m = 0, ll _c = OO) : m(_m), c(_c) {}
    // safe evaluation using __int128 and clamp to avoid undefined behavior
    ll eval(ll x) const {
        __int128 val = (__int128)m * (__int128)x + (__int128)c;
        if (val > ( (__int128)LLONG_MAX / 2 )) return LLONG_MAX;
        if (val < ( (__int128)LLONG_MIN / 2 )) return LLONG_MIN;
        return (ll)val;
    }
    ll operator()(ll x) const { return eval(x); }
};

struct Node {
    Line line;
    Node* left = nullptr;
    Node* right = nullptr;
    Node(const Line &L = Line()) : line(L) {}
};

// change record (either pointer change or a line content change)
struct Change {
    bool isLineChange;
    // pointer change:
    Node** ptrAddr = nullptr;
    Node* oldPtr = nullptr;
    // line change:
    Node* node = nullptr;
    Line oldLine;
    // constructors
    Change(Node** p, Node* old) : isLineChange(false), ptrAddr(p), oldPtr(old) {}
    Change(Node* nd, const Line &oldL) : isLineChange(true), node(nd), oldLine(oldL) {}
};

vector<Change> changeLog;
vector<int> insertCheckpoints;

// record pointer change (address of the Node* variable and its old value)
inline void record_ptr(Node*& p) {
    changeLog.emplace_back(&p, p);
}

// record a node->line change
inline void record_line(Node* node) {
    changeLog.emplace_back(node, node->line);
}

void rollbackTo(int checkpoint) {
    while ((int)changeLog.size() > checkpoint) {
        Change ch = changeLog.back();
        changeLog.pop_back();
        if (!ch.isLineChange) {
            // pointer change: restore pointer
            *ch.ptrAddr = ch.oldPtr;
        } else {
            // line change: restore node->line
            ch.node->line = ch.oldLine;
        }
    }
}

void rollbackLastInsert() {
    if (!insertCheckpoints.empty()) {
        rollbackTo(insertCheckpoints.back());
        insertCheckpoints.pop_back();
    }
}

// Insert implementation (min Li Chao)
void insert_impl(Line newLine, Node*& root, ll l, ll r) {
    if (!root) {
        record_ptr(root);               // record change to this pointer
        root = new Node(newLine);
        return;
    }

    ll m = (l + r) / 2;
    bool lef = newLine.eval(l) < root->line.eval(l);
    bool mid = newLine.eval(m) < root->line.eval(m);

    if (mid) {
        record_line(root);             // record old line BEFORE swapping
        swap(root->line, newLine);
    }

    if (r - l == 1) return;

    if (lef != mid) insert_impl(newLine, root->left, l, m);
    else insert_impl(newLine, root->right, m, r);
}

// Public API for tracked insertion
void insert(Line newLine, Node*& root, ll l = -N, ll r = +N) {
    insertCheckpoints.push_back((int)changeLog.size());
    insert_impl(newLine, root, l, r);
}

// query min at x
ll query(ll x, Node* root, ll l = -N, ll r = +N) {
    if (!root) return OO;
    ll m = (l + r) / 2;
    ll res = root->line.eval(x);
    if (r - l == 1) return res;
    if (x < m) return min(res, query(x, root->left, l, m));
    else return min(res, query(x, root->right, m, r));
}


Node *root = nullptr;
int n;
vector<int> v, c;
vector<vector<pair<int, int>>> adj;

vector<int> dp;
void dfs(int node , int p = -1 , int d = 0)
{
    if(p == -1) dp[node] = 0;
    else dp[node] = query(v[node] , root) + v[node] * d + c[node];

    insert(Line(-d , dp[node]) , root);

    for(auto [child , len] : adj[node])
    {
        if(child == p)continue;
        dfs(child , node , d + len);
    }
    rollbackLastInsert();
}

signed main() {
    fast;


//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);

    cin >> n;
    dp = v = c = vector<int>(n);
    adj.resize(n);

    for (int i = 0; i < n - 1; ++i) {
        int u, vv, d;
        cin >> u >> vv >> d;
        u--;
        vv--;
        adj[u].emplace_back(vv, d);
        adj[vv].emplace_back(u, d);
    }

    for (int i = 1; i < n; ++i) {
        cin >> c[i] >> v[i];
    }


    dfs(0);

    for(int i = 1 ; i < n ; i++) cout << dp[i] << " ";
    cout<<'\n';



}
#Verdict Execution timeMemoryGrader output
Fetching results...