제출 #760580

#제출 시각아이디문제언어결과실행 시간메모리
760580Kihihihi밀림 점프 (APIO21_jumps)C++17
100 / 100
1199 ms66864 KiB
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <numeric>
#include <cmath>
#include <cassert>
#include <ctime>
#include <chrono>
#include <cstdio>
#include <random>
#include <vector>
#include <string>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <deque>
#include <queue>
#include <bitset>
#include <list>
#include <fstream>
#include <functional>
#include <complex>
#include "jumps.h"
using namespace std;
mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());

const int INF = 1e9, MOD = 1e9 + 7, MOD2 = 998244353, LOG = 20;
const long double EPS = 1e-9, PI = acos(-1);

struct sparse_table
{
    int n;
    vector<int> h, lg2;
    vector<vector<int>> t;

    sparse_table() {}

    sparse_table(vector<int>& in)
    {
        n = in.size();
        h = in;
        lg2.resize(n + 1);
        for (int i = 2; i < n + 1; i++)
        {
            lg2[i] = lg2[i / 2] + 1;
        }

        t.resize(lg2[n] + 1);
        t[0].resize(n);
        iota(t[0].begin(), t[0].end(), 0);
        for (int i = 1; i < t.size(); i++)
        {
            int len = (1ll << i);
            t[i].resize(n - len + 1);
            for (int j = 0; j < t[i].size(); j++)
            {
                if (h[t[i - 1][j]] > h[t[i - 1][j + len / 2]])
                {
                    t[i][j] = t[i - 1][j];
                }
                else
                {
                    t[i][j] = t[i - 1][j + len / 2];
                }
            }
        }
    }

    int get(int l, int r)
    {
        int lg = lg2[r - l + 1];
        if (h[t[lg][l]] > h[t[lg][r - (1ll << lg) + 1]])
        {
            return t[lg][l];
        }
        else
        {
            return t[lg][r - (1ll << lg) + 1];
        }
    }
};

sparse_table sptb;
vector<int> v, gtl, gtr;
vector<vector<int>> bingt, binls;

void init(int n, std::vector<int> h)
{
    v = h;
    sptb = sparse_table(h);

    gtl.resize(n, -1);
    vector<int> st;
    for (int i = 0; i < n; i++)
    {
        while (st.size() && v[st.back()] <= v[i])
        {
            st.pop_back();
        }
        if (st.size())
        {
            gtl[i] = st.back();
        }
        st.push_back(i);
    }

    gtr.resize(n, n);
    st = {};
    for (int i = n - 1; i > -1; i--)
    {
        while (st.size() && v[st.back()] <= v[i])
        {
            st.pop_back();
        }
        if (st.size())
        {
            gtr[i] = st.back();
        }
        st.push_back(i);
    }

    bingt.resize(n, vector<int>(LOG, -1));
    binls.resize(n, vector<int>(LOG, -1));
    for (int i = 0; i < n; i++)
    {
        if (gtl[i] == -1 && gtr[i] == n)
        {
            continue;
        }

        if (gtl[i] == -1)
        {
            bingt[i][0] = binls[i][0] = gtr[i];
        }
        if (gtr[i] == n)
        {
            bingt[i][0] = binls[i][0] = gtl[i];
        }
        if (gtl[i] != -1 && gtr[i] != n)
        {
            if (v[gtl[i]] > v[gtr[i]])
            {
                bingt[i][0] = gtl[i];
                binls[i][0] = gtr[i];
            }
            else
            {
                bingt[i][0] = gtr[i];
                binls[i][0] = gtl[i];
            }
        }
    }
    for (int i = 1; i < LOG; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (binls[j][i - 1] != -1)
            {
                binls[j][i] = binls[binls[j][i - 1]][i - 1];
            }
            if (bingt[j][i - 1] != -1)
            {
                bingt[j][i] = bingt[bingt[j][i - 1]][i - 1];
            }
        }
    }
}

int minimum_jumps(int a, int b, int c, int d)
{
    int mxto = sptb.get(c, d);
    int bsl = a - 1, bsr = b + 1;
    while (bsr - bsl > 1)
    {
        int mid = (bsl + bsr) / 2;
        if (v[sptb.get(mid, b)] < v[mxto])
        {
            bsr = mid;
        }
        else
        {
            bsl = mid;
        }
    }
    if (bsr == b + 1)
    {
        return -1;
    }
    a = bsr;

    if (b < c - 1)
    {
        if (v[sptb.get(b + 1, c - 1)] > v[mxto])
        {
            return -1;
        }
    }
    d = mxto;

    if (b == c - 1)
    {
        return 1;
    }

    int fr = sptb.get(a, b);
    int btw = sptb.get(b + 1, c - 1);
    if (v[fr] > v[btw])
    {
        return 1;
    }

    int ans = 0;
    for (int i = LOG - 1; i > -1; i--)
    {
        if (bingt[fr][i] == -1 || v[bingt[fr][i]] >= v[btw])
        {
            continue;
        }

        ans += (1ll << i);
        fr = bingt[fr][i];
    }

    if (bingt[fr][0] != -1 && v[bingt[fr][0]] < v[mxto])
    {
        return ans + 2;
    }

    for (int i = LOG - 1; i > -1; i--)
    {
        if (binls[fr][i] == -1 || v[binls[fr][i]] > v[btw])
        {
            continue;
        }

        ans += (1ll << i);
        fr = binls[fr][i];
    }
    return ans + 1;
}

/*
int fuck(int a, int b, int c, int d)
{
    int n = v.size();
    vector<int> dist(n, INF);
    deque<int> q;
    for (int i = a; i < b + 1; i++)
    {
        dist[i] = 0;
        q.push_back(i);
    }

    while (q.size())
    {
        long long ver = q.front();
        q.pop_front();
        if (gtl[ver] != -1)
        {
            if (dist[gtl[ver]] > dist[ver] + 1)
            {
                dist[gtl[ver]] = dist[ver] + 1;
                q.push_back(gtl[ver]);
            }
        }
        if (gtr[ver] != n)
        {
            if (dist[gtr[ver]] > dist[ver] + 1)
            {
                dist[gtr[ver]] = dist[ver] + 1;
                q.push_back(gtr[ver]);
            }
        }
    }

    int ans = INF;
    for (int i = c; i < d + 1; i++)
    {
        ans = min(ans, dist[i]);
    }
    if (ans == INF)
    {
        return -1;
    }
    return ans;
}

int main()
{
    while (true)
    {
        int N = 100;
        std::vector<int> H(N);
        iota(H.begin(), H.end(), 1);
        shuffle(H.begin(), H.end(), rnd);
        init(N, H);

        vector<int> prr(N);
        iota(prr.begin(), prr.end(), 0);
        shuffle(prr.begin(), prr.end(), rnd);
        vector<int> idk = { prr[0], prr[1], prr[2], prr[3] };
        sort(idk.begin(), idk.end());
        if (minimum_jumps(idk[0], idk[1], idk[2], idk[3]) != fuck(idk[0], idk[1], idk[2], idk[3]))
        {
            cout << "PSODVNOSNDV\n";
            return 0;
        }
        cout << "OK\n";

        sptb = {};
        v = gtl = gtr = {};
        bingt = binls = {};
    }
    return 0;

    int N = 0, Q = 0;
    assert(2 == scanf("%d %d", &N, &Q));
    std::vector<int> H(N);
    for (int i = 0; i < N; ++i)
    {
        assert(1 == scanf("%d", &H[i]));
    }
    init(N, H);

    for (int i = 0; i < Q; ++i)
    {
        int A = 0, B = 0, C = 0, D = 0;
        assert(4 == scanf("%d %d %d %d", &A, &B, &C, &D));
        printf("%d\n", minimum_jumps(A, B, C, D));
    }
    return 0;
}
*/

/*
<3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3
⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠤⠖⠚⢉⣩⣭⡭⠛⠓⠲⠦⣄⡀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⢀⡴⠋⠁⠀⠀⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠳⢦⡀⠀⠀⠀⠀
⠀⠀⠀⠀⢀⡴⠃⢀⡴⢳⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣆⠀⠀⠀
⠀⠀⠀⠀⡾⠁⣠⠋⠀⠈⢧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢧⠀⠀
⠀⠀⠀⣸⠁⢰⠃⠀⠀⠀⠈⢣⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣇⠀
⠀⠀⠀⡇⠀⡾⡀⠀⠀⠀⠀⣀⣹⣆⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⠀
⠀⠀⢸⠃⢀⣇⡈⠀⠀⠀⠀⠀⠀⢀⡑⢄⡀⢀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇
⠀⠀⢸⠀⢻⡟⡻⢶⡆⠀⠀⠀⠀⡼⠟⡳⢿⣦⡑⢄⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇
⠀⠀⣸⠀⢸⠃⡇⢀⠇⠀⠀⠀⠀⠀⡼⠀⠀⠈⣿⡗⠂⠀⠀⠀⠀⠀⠀⠀⢸⠁
⠀⠀⡏⠀⣼⠀⢳⠊⠀⠀⠀⠀⠀⠀⠱⣀⣀⠔⣸⠁⠀⠀⠀⠀⠀⠀⠀⢠⡟⠀
⠀⠀⡇⢀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⢸⠃⠀
⠀⢸⠃⠘⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠁⠀⠀⢀⠀⠀⠀⠀⠀⣾⠀⠀
⠀⣸⠀⠀⠹⡄⠀⠀⠈⠁⠀⠀⠀⠀⠀⠀⠀⡞⠀⠀⠀⠸⠀⠀⠀⠀⠀⡇⠀⠀
⠀⡏⠀⠀⠀⠙⣆⠀⠀⠀⠀⠀⠀⠀⢀⣠⢶⡇⠀⠀⢰⡀⠀⠀⠀⠀⠀⡇⠀⠀
⢰⠇⡄⠀⠀⠀⡿⢣⣀⣀⣀⡤⠴⡞⠉⠀⢸⠀⠀⠀⣿⡇⠀⠀⠀⠀⠀⣧⠀⠀
⣸⠀⡇⠀⠀⠀⠀⠀⠀⠉⠀⠀⠀⢹⠀⠀⢸⠀⠀⢀⣿⠇⠀⠀⠀⠁⠀⢸⠀⠀
⣿⠀⡇⠀⠀⠀⠀⠀⢀⡤⠤⠶⠶⠾⠤⠄⢸⠀⡀⠸⣿⣀⠀⠀⠀⠀⠀⠈⣇⠀
⡇⠀⡇⠀⠀⡀⠀⡴⠋⠀⠀⠀⠀⠀⠀⠀⠸⡌⣵⡀⢳⡇⠀⠀⠀⠀⠀⠀⢹⡀
⡇⠀⠇⠀⠀⡇⡸⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠮⢧⣀⣻⢂⠀⠀⠀⠀⠀⠀⢧
⣇⠀⢠⠀⠀⢳⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⡎⣆⠀⠀⠀⠀⠀⠘
⢻⠀⠈⠰⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠰⠘⢮⣧⡀⠀⠀⠀⠀
⠸⡆⠀⠀⠇⣾⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠆⠀⠀⠀⠀⠀⠀⠀⠙⠳⣄⡀⢢⡀
<3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3
*/

컴파일 시 표준 에러 (stderr) 메시지

jumps.cpp: In constructor 'sparse_table::sparse_table(std::vector<int>&)':
jumps.cpp:53:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   53 |         for (int i = 1; i < t.size(); i++)
      |                         ~~^~~~~~~~~~
jumps.cpp:57:31: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   57 |             for (int j = 0; j < t[i].size(); j++)
      |                             ~~^~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...