Submission #764407

#TimeUsernameProblemLanguageResultExecution timeMemory
764407shjeongHarbingers (CEOI09_harbingers)C++14
30 / 100
118 ms65536 KiB
#include <iostream>
#include <cmath>
#include <algorithm>
#include <numeric>
#include <cstring>
#include <vector>
#include <string>
#include <climits>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <bitset>
#include <cassert>
#include <list>
/******************************************************************************
 * dp[i] := i에서 1까지 가는데 걸리는 최솟값
 * i에서 j까지 가는데에 전령 i를 이용해야 함. 이후는 그냥 dp[j]
 * dp[i] = min(j is element of i's ancestor) (dp[j] + (dis(i)-dis(j)) * Vi)+Si
 * =min(-dis(j)*Vi +dp[j]) + Si + dis(i)*Vi
 * dfs상에서 자기 정점이 끝날 때 li-chao에서 직선 제거
 * 구현할 때는 li-chao에서 i 정점의 직선을 넣을 때, 변화한 위치를 벡터에 저장
 * vector<pair<node,node>>changed[i] : i.first가 i.second로 변화함
 *
*******************************************************************************/
using namespace std;
#define fast ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define all(x) x.begin(), x.end()
#define rll(x) x.rbegin(), x.rend()
#define comp(x) x.erase(unique(all(x)), x.end())
#define MOD 998244353
typedef long long ll;
const ll inf1 = 2e9, inf2 = 2e18;
struct Line{
    ll a,b;
    ll f(ll x){return a*x+b;}
};
Line max(Line a, Line b, ll x){
    return a.f(x) >= b.f(x) ? a : b;
}
Line min(Line a, Line b, ll x){
    return a.f(x) <= b.f(x) ? a : b;
}
struct Node{
    int l,r;
    ll s,e;
    Line line;
};
struct asdf{
    int x;
    Node before;
    int num;
};
struct seg{
    vector<Node> tree;
    void init(ll s, ll e){
        tree.push_back({-1,-1,s,e,{0,inf2}});
    }
    deque<asdf> changed;
    inline void upd(ll node, Line k, int num){
        auto push = [&](int x, Node a, int c) -> void {
            changed.push_back({x,a,c});
        };
        ll s = tree[node].s, e = tree[node].e;
        Line low = min(tree[node].line, k, s), high = max(tree[node].line, k, s);
        if(low.f(e) <= high.f(e)){
            auto cur = tree[node];
            tree[node].line = low;
            push(num, cur, node);
            return;
        }
        ll mid = s+e>>1;
        if(low.f(mid) < high.f(mid)){
            auto cur = tree[node];
            tree[node].line = low;
            if(tree[node].r == -1){
                push(num, {-2,-2,-2,-2,{-2,-2}}, tree.size());
                tree[node].r = tree.size();
                tree.push_back({-1,-1,mid+1,e,{0,inf2}});
            }
            push(num, cur, node);
            upd(tree[node].r, high, num);
        }
        else{
            auto cur = tree[node];
            tree[node].line = high;
            if(tree[node].l == -1){
                push(num, {-2,-2,-2,-2,{-2,-2}}, tree.size());
                tree[node].l = tree.size();
                tree.push_back({-1,-1,s,mid,{0,inf2}});
            }
            push(num, cur, node);
            upd(tree[node].l, low, num);
        }
    }
    inline ll query(ll node, ll x){
        if(node==-1)return inf2;
        ll s = tree[node].s, e = tree[node].e;
        ll mid = s+e>>1;
        if(x<=mid)return min(tree[node].line.f(x), query(tree[node].l, x));
        return min(tree[node].line.f(x), query(tree[node].r, x));
    }
    inline void rollback(ll x){
        while(changed.size() and changed.back().x == x){
            auto [x,a,i] = changed.back();
            changed.pop_back();
            if(a.l==-2)tree.pop_back();
            else tree[i] = a;
        }
    }
} seg;
ll n;
bool visited[101010];
vector<pair<int,ll>> adj[101010];
ll dp[101010];
ll depth[101010];
ll s[101010], v[101010];
void dfs(ll x, ll y){
    visited[x]=1;
    depth[x]=y;
    if(x!=1)dp[x] = seg.query(0, v[x])+(ll)s[x]+depth[x]*v[x];
    seg.upd(0, {-depth[x], dp[x]}, x);
    for(auto [next,w] : adj[x]){
        if(visited[next])continue;
        dfs(next, y+w);
    }
    seg.rollback(x);
}
int main(){
    fast;
    cin>>n;
    seg.init(-inf1, inf1);
    for(int i = 0 ; i < n-1 ; i++){
        ll a,b,c; cin>>a>>b>>c;
        adj[a].push_back({b,c});
        adj[b].push_back({a,c});
    }
    for(int i = 2 ; i <= n ; i++){
        cin>>s[i]>>v[i];
    }
    dfs(1,0);
    for(int i = 2 ; i <= n ; i++)cout<<dp[i]<<" ";
}

Compilation message (stderr)

harbingers.cpp: In member function 'void seg::upd(ll, Line, int)':
harbingers.cpp:72:19: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   72 |         ll mid = s+e>>1;
      |                  ~^~
harbingers.cpp: In member function 'll seg::query(ll, ll)':
harbingers.cpp:99:19: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   99 |         ll mid = s+e>>1;
      |                  ~^~
harbingers.cpp: In member function 'void seg::rollback(ll)':
harbingers.cpp:105:18: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  105 |             auto [x,a,i] = changed.back();
      |                  ^
harbingers.cpp: In function 'void dfs(ll, ll)':
harbingers.cpp:123:14: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  123 |     for(auto [next,w] : adj[x]){
      |              ^
#Verdict Execution timeMemoryGrader output
Fetching results...