Submission #402559

# Submission time Handle Problem Language Result Execution time Memory
402559 2021-05-12T00:33:34 Z blue Harbingers (CEOI09_harbingers) C++17
0 / 100
1000 ms 33312 KB
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;

/*
Let anc[u][x] be the x'th ancestor of u.
dp[u] =def= amount of time needed for message to be delivered from u to 1.

dp[1] =def= 0
dp[u] = min{S[u] + V[u]*dist(u, v) + dp[v] | v in anc[u]}
      = min{S[u] + V[u]*(dist1[u] - dist1[v]) + dp[v] | v in anc[u]}

dp[u] min= S[u] + V[u]*dist1[u]   +   -dist1[v]*V[u] + dp[v]
                                            a * x   +  b
*/
long long INF = 2'000'000'000'000'000'000;

vector<int> edge[100001], dist[100001]; //edges, weights of edges
vector<long long> S(100001, 0), V(100001, 0); //starting time, reciprocal speed

vector<long long> dist1(100001, 0);
int cht_anc[100001][19];
vector<int> prev_node(100001);
vector<long long> prev_dist(100001);

void dfs1(int u)
{
    for(int i = 0; i < edge[u].size(); i++)
    {
        int v = edge[u][i];
        long long d = dist[u][i];

        if(prev_node[u] == v) continue;
        prev_node[v] = u;
        prev_dist[v] = d;
        dist1[v] = dist1[u] + prev_dist[v];

        dfs1(v);
    }
}


vector<long long> a(100001), b(100001);
vector<long long> dp(100001);

// long long a(int u)
// {
//     return -dist1[u];
// }
//
// long long b(int u)
// {
//     return dp[u];
// }

bool intersect_comp(int e1, int e2, long long x)
{ /*a[e1]*x + b[e1] = a[e2]*x + b[e2]
    x_e = (b[e2] - b[e1])/(a[e1] - a[e2])
    */
    cerr << "intersect comp " << e1 << ' ' << e2 << ' ' << double(b[e2] - b[e1])/double(a[e1] - a[e2]) << ' ' << x << ' ' << ((b[e2] - b[e1]) < (a[e1] - a[e2])*x) << '\n';
    return (b[e2] - b[e1]) < (a[e1] - a[e2])*x; //Be very careful with the sign.
}

bool line_intersect_comp(int e1, int e2, int f1, int f2)
{//intersect(e1, e2) < intersect(f1, f2)
    if(e2 == 1) return 1;
    return (b[e2] - b[e1])*(a[f1] - a[f2]) < (b[f2] - b[f1])*(a[e1] - a[e2]);
}

/*
i, i+1, L
Line i+2 is a good insertion if intersect(i, i+1) < intersect(i+1, i+2)
We need to binary search for the largest line i such that intersect(i-1, i) < intersect(i, L)
*/

void dfs2(int u)
{
    for(int v: edge[u])
    {
        if(prev_node[u] == v) continue;

        /*w is the ideal harbinger for the harbinger from v to go to
        Using binary lifting, we search for the edge on which f(x) is maximised
        */

        int w = u;
        for(int e = 18; e >= 0; e--)
        {
            if(cht_anc[w][e] == 1) continue;
            cerr << "v = " << v << ", e = " << e << ", w = " << cht_anc[w][e] << " | ";
            if(intersect_comp( prev_node[cht_anc[w][e]] , cht_anc[w][e], V[v] ) == 0)
            {
                w = cht_anc[w][e];
                cerr << "yes\n";
            }
            cerr << "no\n";
        }

        dp[v] = S[v] + V[v]*(dist1[v] - dist1[w]) + dp[w];

        cerr << v << ' ' << w << ' ' << dp[v] << '\n';
        w = cht_anc[w][0];
        dp[v] = min(dp[v], S[v] + V[v]*(dist1[v] - dist1[w]) + dp[w]);

        a[v] = -dist1[v];
        b[v] = dp[v];

        cerr << "adding line at " << v << ": " << a[v] <<"*x+" << b[v] << '\n';

        w = u;
        for(int e = 18; e >= 0; e--)
        {
            int temp = cht_anc[w][e];
            if(line_intersect_comp(prev_node[temp], temp, temp, v))
                continue;
            w = temp;
        }


        if(!line_intersect_comp(prev_node[w], w, w, v))
            w = cht_anc[w][0];

        cerr << "cht_parent = " << w << '\n';

        cht_anc[v][0] = w;
        for(int e = 1; e <= 18; e++)
            cht_anc[v][e] = cht_anc[ cht_anc[v][e-1] ][e-1];

        dfs2(v);
    }
}

int main()
{
    int N;
    cin >> N;

    for(int j = 1; j <= N-1; j++)
    {
        int u, v, d;
        cin >> u >> v >> d;

        edge[u].push_back(v);
        dist[u].push_back(d);

        edge[v].push_back(u);
        dist[v].push_back(d);
    }

    for(int i = 2; i <= N; i++)
        cin >> S[i] >> V[i];

    prev_node[1] = 1;
    prev_dist[1] = 0;
    dfs1(1);


    // for(int i = 1; i <= N; i++)
    // {
    //     cerr << "i = " << i << ": ";
    //     cerr << S[i] << ' ' << V[i] << ' ' << dist1[i] << " " << prev_node[i] << ' ' << prev_dist[i] << '\n';
    // }

    dp[1] = 0;
    for(int e = 0; e <= 18; e++)
        cht_anc[1][e] = 1;
    V[1] = S[1] = 0;
    a[1] = b[1] = 0;
    dfs2(1);

    for(int i = 2; i <= N; i++) cout << dp[i] << ' ';
    cout << '\n';
}

Compilation message

harbingers.cpp: In function 'void dfs1(int)':
harbingers.cpp:29:22: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   29 |     for(int i = 0; i < edge[u].size(); i++)
      |                    ~~^~~~~~~~~~~~~~~~
# Verdict Execution time Memory Grader output
1 Incorrect 13 ms 10828 KB Output isn't correct
2 Incorrect 626 ms 12920 KB Output isn't correct
3 Execution timed out 1093 ms 22016 KB Time limit exceeded
4 Execution timed out 1094 ms 25796 KB Time limit exceeded
5 Execution timed out 1095 ms 30204 KB Time limit exceeded
6 Execution timed out 1094 ms 33312 KB Time limit exceeded
7 Execution timed out 1095 ms 24780 KB Time limit exceeded
8 Execution timed out 1087 ms 28168 KB Time limit exceeded
9 Execution timed out 1088 ms 29928 KB Time limit exceeded
10 Execution timed out 1088 ms 29312 KB Time limit exceeded