답안 #425205

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
425205 2021-06-12T15:35:12 Z two_sides 고대 책들 (IOI17_books) C++17
0 / 100
2000 ms 825580 KB
#include "books.h"
#include <bits/stdc++.h>

using namespace std;

namespace {
#define fi first
#define se second

    using ll = long long;

    struct segment_tree {
    #define il i * 2
    #define ir i * 2 + 1

        vector <int> val;
        int n, x, y, res;

        void build(int i, int l, int r,
        const vector <int> &idx) {
            if (l == r) val[i] = idx[l];
            else {
                int m = (l + r) / 2;
                build(il, l, m, idx);
                build(ir, m + 1, r, idx);
                val[i] = max(val[il], val[ir]);
            }
        }

        void init(const vector <int> &idx) {
            n = idx.size();
            val.resize(n * 4);
            build(1, 0, n - 1, idx);
        }

        void init(int n) {
            this->n = n;
            val.assign(n * 4, -1e9);
        }

        void rep(int i, int l, int r, int v) {
            if (l == r) val[i] = v;
            else {
                int m = (l + r) / 2;
                if (m >= x) rep(il, l, m, v);
                else rep(ir, m + 1, r, v);
                val[i] = max(val[il], val[ir]);
            }
        }

        void get(int i, int l, int r) {
            if (l >= x && r <= y) {
                res = max(res, val[i]);
                return;
            }
            int m = (l + r) / 2;
            if (m >= x) get(il, l, m);
            if (m < y) get(ir, m + 1, r);
        }

        void rep(int p, int v) {
            x = p; rep(1, 0, n - 1, v);
        }

        int get(int l, int r) {
            x = l; y = r; res = -1e9;
            get(1, 0, n - 1); return res;
        }
    };

    vector <int> lef, rig, scc;
    vector <vector <int>> own, cmp;
    segment_tree seg1, seg2;
    int timer = 0;
    stack <int> stk;
    vector <int> num, low;

    void tarjan(int u) {
        low[u] = num[u] = ++timer;
        for (int i : own[u]) {
            seg1.rep(i, -1);
            seg2.rep(i, -low[u]);
        }
        stk.push(u);
        int v = seg1.get(lef[u], rig[u]);
        while (~v) {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        low[u] = min(low[u], -seg2.get(lef[u], rig[u]));
        if (num[u] == low[u]) {
            cmp.emplace_back();
            do {
                v = stk.top(); stk.pop();
                cmp.back().push_back(v);
                scc[v] = cmp.size() - 1;
                num[v] = low[v] = 1e9;
                scc[v] =  timer;
            } while (v != u);
        }
    }
}

ll minimum_walk(vector<int> p, int s) {
    int cnt = 0, n = p.size();
    vector <int> idx(n, -1);
    for (int i = 0; i < n; i++) {
        if (~idx[i]) continue;
        int u = i;
        lef.push_back(i);
        rig.push_back(i);
        own.emplace_back();
        while (idx[u] < 0) {
            own[cnt].push_back(u);
            lef[cnt] = min(lef[cnt], u);
            rig[cnt] = max(rig[cnt], u);
            idx[u] = cnt; u = p[u];
        }
        cnt++;
    }
    scc.resize(cnt);
    num.resize(cnt); low.resize(cnt);
    seg1.init(idx); seg2.init(n);
    for (int i = 0; i < cnt; i++)
        if (!num[i]) tarjan(i);
    reverse(cmp.begin(), cmp.end());
    num.assign(cmp.size(), 0);
    vector <pair <int, int>> tmp;
    int mi = s, ma = s;
    seg1.init(idx); seg2.init(n);
    for (int i = 0; i < cmp.size(); i++) {
        if (!num[i]) {
            int l = -1, r = n;
            for (int j : cmp[i])
                for (int k : own[j]) {
                    if (k < s) l = max(l, k);
                    if (k > s) r = min(r, k);
                    seg1.rep(k, -1);
                }
            if (l >= 0 && r < n) {
                tmp.emplace_back(l, r);
                seg2.rep(r, r);
            } else if (l >= 0) mi = min(mi, l);
            else if (r < n) ma = max(ma, r);
        }
        // for (int j : cmp[i])
        //     for (int k : own[j])
        //         seg1.rep(k, -1);
        // for (int j : cmp[i]) {
        //     int k = seg1.get(lef[j], rig[j]);
        //     while (k >= 0) {
        //         num[scc[k]] = true;
        //         for (int l : own[k])
        //             seg1.rep(l, -1);
        //         k = seg1.get(lef[j], rig[j]);
        //     }
        // }
    }
    sort(tmp.rbegin(), tmp.rend());
    long long res = 2ll * (max(ma, seg2.val[1]) - mi);
    for (auto &p : tmp) {
        seg2.rep(p.se, -1);
        res = min(res, 2ll * (max(ma, seg2.val[1]) - min(mi, p.fi)));
    }
    for (int i = 0; i < n; i++)
        res += abs(i - p[i]);
    return res;
    return 0;
}

Compilation message

books.cpp: In function '{anonymous}::ll minimum_walk(std::vector<int>, int)':
books.cpp:131:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  131 |     for (int i = 0; i < cmp.size(); i++) {
      |                     ~~^~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 204 KB Output is correct
2 Execution timed out 2108 ms 825580 KB Time limit exceeded
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 204 KB Output is correct
2 Execution timed out 2108 ms 825580 KB Time limit exceeded
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 204 KB Output is correct
2 Execution timed out 2108 ms 825580 KB Time limit exceeded
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Execution timed out 2108 ms 582104 KB Time limit exceeded
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 204 KB Output is correct
2 Execution timed out 2108 ms 825580 KB Time limit exceeded
3 Halted 0 ms 0 KB -