Submission #1335586

#TimeUsernameProblemLanguageResultExecution timeMemory
1335586toma_ariciuRail (IOI14_rail)C++20
100 / 100
160 ms98644 KiB
#include <bits/stdc++.h>
#include "rail.h"

using namespace std;

const int maxN = 5005;
int dist[maxN][maxN];

int query(int x, int y) {
    if (dist[x][y] != -1) {
        return dist[x][y];
    }

    int val = getDistance(x, y);
    dist[x][y] = val;
    dist[y][x] = val;

    return val;
}

int findDistToZero(int type, int poz, int poz0, vector <int> &known, int stype[], int location[]) {
    if (type == 2 && poz > poz0) {
        return poz - poz0;
    }
    if (type == 1) {
        int d = 1e9;
        for (int x : known) {
            if (stype[x] == 2 && location[x] > max(poz, poz0)) {
                d = min(d, 2 * location[x] - poz - poz0);
            }
        }
        return d;
    }

    int bestL = -1, bestR = -1;
    for (int x : known) {
        if (stype[x] == 1) {
            if (location[x] > poz) {
                continue;
            }

            if (bestL == -1 || location[x] > location[bestL]) {
                bestL = x;
            }
        } else if (stype[x] == 2) {
            if (location[x] < poz0) {
                continue;
            }

            if (bestR == -1 || location[x] < location[bestR]) {
                bestR = x;
            }
        }
    }

    // cout << bestL << ' ' << bestR << '\n';
    // cout << poz << ' ' << location[bestL] << ' ' << location[bestR] << '\n';

    return location[bestR] - poz0 + location[bestR] - location[bestL] + poz - location[bestL];
}

void findLocation(int N, int first, int location[], int stype[])
{
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            dist[i][j] = -1;
        }
    }
    for (int i = 0; i < N; i++) {
        dist[i][i] = 0;
    }

    location[0] = first;
    stype[0] = 1;

    int best = -1;
    for (int i = 1; i < N; i++) {
        if (best == -1 || query(0, i) < query(0, best)) {
            best = i;
        }
    }

    location[best] = location[0] + query(0, best);
    stype[best] = 2;

    vector <pair <int, int>> v;
    for (int i = 1; i < N; i++) {
        if (best == i) {
            continue;
        }
        v.push_back({dist[0][i], i});
    }

    sort(v.begin(), v.end());
    int l = 0, r = best;
    vector <int> known = {0, best};

    // for (int x : known) {
    //     cout << x << ' ' << location[x] << ' ' << stype[x] << '\n';
    // }

    for (int i = 0; i < v.size(); i++) {
        auto [d, x] = v[i];
        // cout << x << '\n';    
        // cout << "KNOWN:\n";
        // for (int y : known) {
            // cout << y << ' ' << location[y] << ' ' << stype[y] << '\n';
        // }
        // cout << '\n';
        int distToLeft = query(l, x);
        int distToRight = query(x, r);
        // cout << x << ' ' << distToLeft << ' ' << distToRight << '\n';
        /// CHECKING STYPE = 1:
        bool ok = 0;
        location[x] = location[r] - distToRight; 
        for (int y : known) {
            if (stype[y] == 1) {
                continue;
            }
            if (location[y] < location[x]) {
                continue;
            }
            // cout << "Trying: ";
            // cout << y << ' ' << location[y] - location[l] + location[y] - location[x] << '\n';
            if (location[y] - location[l] + location[y] - location[x] == distToLeft) {
                ok = 1;
            }
        }
        if (ok) {
            if (location[x] < location[l]) {
                l = x;
            }

            // cout << "Solution 1 for " << x << '\n';
            known.push_back(x);
            stype[x] = 1;
            continue;
        }

        /// CHECKING STYPE = 2
        location[x] = location[l] + distToLeft;
        for (int y : known) {
            if (stype[y] == 2) {
                continue;
            }
            if (location[y] > location[x]) {
                continue;
            }

            if (location[r] - location[y] + location[x] - location[y] == distToRight) {
                ok = 1;
            }
        }

        if (ok) {
            if (location[x] > location[r]) {
                r = x;
            }
            // cout << "Solution 2 for " << x << '\n';
            known.push_back(x);
            stype[x] = 2;
            continue;
        }



        int test1 = findDistToZero(1, location[r] - distToRight, first, known, stype, location);
        int test2 = findDistToZero(2, location[l] + distToLeft, first, known, stype, location);

        // if (x == 3) {
        //     cout << "Values:\n";
        //     cout << l << ' ' << location[l] << ' ' << distToLeft << '\n';
        //     cout << "Left:  " << l << ' ' << location[l] << '\n';
        //     cout << "Right:  " << r << ' ' << location[r] << '\n';

        //     cout << test1 << ' ' << test2 << ' ' << query(0, x) << '\n';
        // }

        if (test2 == query(0, x)) {
            stype[x] = 2;
            location[x] = location[l] + distToLeft;
            if (location[x] > location[r]) {
                r = x;
            }
        } else if (test1 == query(0, x)) {
            stype[x] = 1;
            location[x] = location[r] - distToRight;
            if (location[x] < location[r]) {
                l = x;
            }
        } else {
            exit(-1);
        }

        // cout << "Emergency for " << x << '\n';
        known.push_back(x);

        // exit(-1);
    }

    // for (int i = 0; i < N; i++) {
    //     cout << stype[i] << ' ' << location[i] << '\n';
    // }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...