제출 #1268005

#제출 시각아이디문제언어결과실행 시간메모리
1268005LaMatematica14고대 책들 (IOI17_books)C++20
0 / 100
2093 ms320 KiB
#include <bits/stdc++.h>
using namespace std;

long long minimum_walk(vector<int> p, int s) {
    long long ans = 0, N = p.size();
    for (int i=0; i<N; i++) ans += abs(p[i]-i);
    int last_ordered = N, first_unordered = -1;
    for (int i = 0; i < s; i++) {
        if (p[i] != i) break;
        first_unordered = i;
    }
    for (int i = N-1; i > s; i--) {
        if (p[i] != i) break;
        last_ordered = i;
    }
    if (last_ordered == 0) return 0;

    auto expand = [&](int start, int l, int r) -> pair<int, int> {
        int m_l = l, m_r = r;
        m_l = min(start, m_l); m_r = max(start, m_r);
        while (m_l != l || m_r != r) {
            for (; r <= m_r; r++) {
                m_r = max(m_r, p[r]);
                m_l = min(m_l, p[r]);
            }
            for (; l >= m_l; l--) {
                m_r = max(m_r, p[l]);
                m_l = min(m_l, p[l]);
            }
        }
        return {l, r};
    };

    int curr_seg_left = s, curr_seg_right = s;
    tie(curr_seg_left, curr_seg_left) = expand(s, s, s); 
    while (1) {
        int ns_left = 0, ns_right = 0;
        int superseg_left = -1, superseg_right = -1;
        // count segments to the left
        while (curr_seg_left > first_unordered+1) {
            auto [new_left, new_right] = expand(curr_seg_left-1, curr_seg_left, curr_seg_right);
            if (new_right > curr_seg_right) {
                // found superseg
                superseg_left = new_left;
                superseg_right = new_right;
                //...
                break;
            }
            else {
                ns_left++;
                curr_seg_left = new_left;
            }
        }
         
        // count segments to the right
        while (curr_seg_right < last_ordered-1) {
            auto [new_left, new_right] = expand(curr_seg_right+1, curr_seg_left, curr_seg_right);
            if (new_left < curr_seg_left) {
                // found superseg
                assert(superseg_left == new_left);
                assert(superseg_right == new_right);
                // ...
                break;
            }
            else {
                ns_right++;
                curr_seg_right = new_right;
            }
        }

        // check minim or exit
        if (superseg_left != curr_seg_left) {
            assert(superseg_right != curr_seg_right);
            ans += min(ns_left, ns_right)+1;
            curr_seg_left = superseg_left;
            curr_seg_right = superseg_right;
        }
        else {
            ans += (ns_left+ns_right-1)*2;
            return ans;
        }
    }
    return ans;
}
#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...