제출 #90385

#제출 시각아이디문제언어결과실행 시간메모리
90385Alexa2001Railway Trip (JOI17_railway_trip)C++17
45 / 100
618 ms67644 KiB
#include <bits/stdc++.h>

using namespace std;

const int Nmax = 1e5 + 5, Kmax = 22;

int n, q, k;
int a[Nmax], dist[Nmax], st[Nmax];
vector<int> v[Nmax];

int goL[Nmax][Kmax], goR[Nmax][Kmax], L[Nmax][Kmax], R[Nmax][Kmax], cnt[Kmax][Nmax];

int cate(int tip, int x, int y)
{
    return cnt[tip][y] - cnt[tip][x-1];
}

int walk(int x, int y)
{
    if(x > y) swap(x, y);
    int train = min(a[x], a[y]);
    return cate(train, x+1, y);
}

int dijkstra(int x, int y)
{
    queue<int> q;
    int i;
    for(i=1; i<=n; ++i) dist[i] = -1;

    dist[x] = 0;
    q.push(x);

    while(q.size())
    {
        int node = q.front();
        q.pop();

        for(auto it : v[node])
            if(dist[it] == -1)
            {
                dist[it] = dist[node] + 1;
                q.push(it);
            }
    }
    return dist[y];
}

void add_edge(int x, int y)
{
    v[x].push_back(y);
    v[y].push_back(x);
}

void brute()
{
    int i, nr = 0;
    for(i=1; i<=n; ++i)
    {
        while(nr && a[st[nr]] < a[i]) --nr;
        if(nr) add_edge(i, st[nr]);
        st[++nr] = i;
    }
    nr = 0;
    for(i=n; i; --i)
    {
        while(nr && a[st[nr]] < a[i]) --nr;
        if(nr) add_edge(i, st[nr]);
        st[++nr] = i;
    }

    while(q--)
    {
        int x, y;
        cin >> x >> y;
        cout << dijkstra(x, y) - 1 << '\n';
    }
}

void solve0()
{
    int i, j, t;

    /// sume partiale
    for(i=1; i<=n; ++i)
    {
        for(j=1; j<=k; ++j)
            cnt[j][i] = cnt[j][i-1];
        for(j=a[i]; j; --j) cnt[j][i]++;
    }

    /// primul la stanga cu valuarea >= j
    for(i=1; i<=n; ++i)
    {
        for(j=1; j<=k; ++j)
            L[i][j] = L[i-1][j];
        for(j=a[i]; j; --j) L[i][j] = i;
    }

    /// primul la dreapta cu valuarea >= j
    for(i=n; i; --i)
    {
        for(j=1; j<=k; ++j)
            R[i][j] = R[i+1][j];
        for(j=a[i]; j; --j) R[i][j] = i;
    }

    /// cati pasi imi ia sa ajung in L[i][j] / R[i][j]

    for(i=1; i<=k; ++i)
    {
        for(j=1; j<=n; ++j)
        {
            goL[j][i] = goR[j][i] = n+5;

            if(a[j] >= i) goL[j][i] = goR[j][i] = 0;
                else
                {
                    for(t=1; t < i; ++t)
                    {
                        goL[j][i] = min(goL[j][i], walk(L[j][i], L[j][t]) + goL[j][t]);
                        goL[j][i] = min(goL[j][i], walk(L[j][i], R[j][t]) + goR[j][t]);
                    }

                    for(t=1; t < i; ++t)
                    {
                        goR[j][i] = min(goR[j][i], walk(R[j][i], L[j][t]) + goL[j][t]);
                        goR[j][i] = min(goR[j][i], walk(R[j][i], R[j][t]) + goR[j][t]);
                    }
                }
        }
    }

    while(q--)
    {
        int x, y;
        cin >> x >> y;

        int ans = n + 5;
        for(t=1; t<=k; ++t)
        {
            int v1, v2, v3, v4;

            v1 = goL[x][t] + goL[y][t] + walk(L[x][t], L[y][t]);
            v2 = goL[x][t] + goR[y][t] + walk(L[x][t], R[y][t]);
            v3 = goR[x][t] + goL[y][t] + walk(R[x][t], L[y][t]);
            v4 = goR[x][t] + goR[y][t] + walk(R[x][t], R[y][t]);

            ans = min(ans, v1);
            ans = min(ans, v2);
            ans = min(ans, v3);
            ans = min(ans, v4);
        }
        cout << ans - 1 << '\n';
    }
}

int main()
{
  //  freopen("input", "r", stdin);
    cin.sync_with_stdio(false);

    int i;
    cin >> n >> k >> q;
    for(i=1; i<=n; ++i) cin >> a[i];

    if(q <= 50) brute();
        else
            if(k<=20) solve0();

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...