# | 제출 시각 | 아이디 | 문제 | 언어 | 결과 | 실행 시간 | 메모리 |
---|---|---|---|---|---|---|---|
522802 | danielliu04 | Harbingers (CEOI09_harbingers) | C++17 | 190 ms | 20588 KiB |
이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
// Link: https://oj.uz/problem/view/CEOI09_harbingers
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ld long double
#define lc (node<<1)+1
#define rc (node<<1)+2
#define endl '\n'
#define INF 1e18
const int max_n = 1e5+5;
int n;
vector<pair<int, ll>> adj[max_n];
ll init[max_n], speed[max_n];
ll dp[max_n]; // this is the answer for this
struct line{
ll m, b;
ll evaluate(ll x){
return m*x+b;
}
ld inter(line other){
return (ld)(other.b - b) / (m - other.m);
}
};
// This is the CHT Structure
line st[max_n];
int st_end = 0; // this is not inclusive
ll get_min_value(ll x){ // finds the min y value given an x value
int low = 0, high = st_end - 1; // find last segment that has a left bound to the left of this x
while(high > low){
int mid = (high + low + 1) / 2;
int prev = mid - 1;
if(st[mid].inter(st[prev]) <= x) low = mid;
else high = mid - 1;
}
return st[low].evaluate(x);
}
int find_pos(line new_line){
if(st_end < 2 || new_line.inter(st[st_end-2]) > st[st_end-1].inter(st[st_end-2])) return st_end;
int low = 1, high = st_end - 1;
while(high > low){
int mid = (low + high) / 2;
// check if new_line can replace mid
if(new_line.inter(st[mid-1]) <= st[mid].inter(st[mid-1])) high = mid;
else low = mid + 1;
}
return low;
}
void dfs(ll prefix = 0, int node = 0, int parent = -1){
// evaluate the answer at this position first
if(node == 0) dp[node] = 0;
else dp[node] = get_min_value(speed[node]) + init[node] + prefix*speed[node];
// cout << node << ' ' << dp[node] << endl;
// insert the current line into stack
int prev_end, pos;
line prev_line, new_line = {-prefix, dp[node]};
pos = find_pos(new_line);
prev_line = st[pos]; // save the deleted line
prev_end = st_end;
st[pos] = new_line;
st_end = pos + 1;
for(auto next: adj[node]){
if(next.first == parent) continue;
dfs(prefix + next.second, next.first, node);
}
// restore the cht to what was before
st_end = prev_end;
st[pos] = prev_line;
}
int main() {
cin >> n;
for(int i = 0; i < n-1; i ++){
int a, b, c; cin >> a >> b >> c; a --; b --;
adj[a].push_back({b, c}); adj[b].push_back({a, c});
}
for(int i = 1; i < n; i ++){
cin >> init[i] >> speed[i];
}
dfs();
for(int i = 1; i < n; i ++){
cout << dp[i] << ' ';
}
cout << endl;
}
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |