結果

問題 No.1460 Max of Min
ユーザー KoD
提出日時 2021-03-31 22:26:57
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 753 ms / 2,000 ms
コード長 3,798 bytes
コンパイル時間 2,133 ms
コンパイル使用メモリ 202,464 KB
最終ジャッジ日時 2025-01-20 03:55:52
ジャッジサーバーID
(参考情報)
judge4 / judge3
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 91
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>

using i32 = std::int32_t;
using u32 = std::uint32_t;
using i64 = std::int64_t;
using u64 = std::uint64_t;
using i128 = __int128_t;
using u128 = __uint128_t;
using isize = std::ptrdiff_t;
using usize = std::size_t;

class rep {
    struct Iter {
        usize itr;
        constexpr Iter(const usize pos) noexcept: itr(pos) { }
        constexpr void operator ++ () noexcept { ++itr; }
        constexpr bool operator != (const Iter& other) const noexcept { return itr != other.itr; }
        constexpr usize operator * () const noexcept { return itr; }
    };
    const Iter first, last;
public:
    explicit constexpr rep(const usize first, const usize last) noexcept: first(first), last(std::max(first, last)) { }
    constexpr Iter begin() const noexcept { return first; }
    constexpr Iter end() const noexcept { return last; }
};

class revrep {
    struct Iter {
        usize itr;
        constexpr Iter(const usize pos) noexcept: itr(pos) { }
        constexpr void operator ++ () noexcept { --itr; }
        constexpr bool operator != (const Iter& other) const noexcept { return itr != other.itr; }
        constexpr usize operator * () const noexcept { return itr; }
    };
    const Iter first, last;
public:
    explicit constexpr revrep(const usize first, const usize last) noexcept: first(last - 1), last(std::min(first, last) - 1) { }
    constexpr Iter begin() const noexcept { return first; }
    constexpr Iter end() const noexcept { return last; }
};

template <class T, T Div = 2>
constexpr T INFTY = std::numeric_limits<T>::max() / Div;

template <class T>
using Vec = std::vector<T>;

struct SemiRing {
    static constexpr SemiRing zero() {
        return SemiRing { -INFTY<i64> };
    }
    static constexpr SemiRing one() {
        return SemiRing { INFTY<i64> };
    }
    i64 x;
    constexpr SemiRing operator + (const SemiRing& other) const {
        return SemiRing { std::max(x, other.x) };
    }
    constexpr SemiRing operator * (const SemiRing& other) const {
        return SemiRing { std::min(x, other.x) };
    }
};

void H_main() {
    // O(K^2 log N) ?
    // + ... max, x ... min の半環
    // 中一でこんなの知ってるのか...
    // kitamasa法 書いたことないんだが
    // A[n+k] = B[0] * A[n] + B[1] * A[n+1] + ... + B[k-1] * A[n+k-1]
    usize K;
    u64 N;
    std::cin >> K >> N;
    Vec<SemiRing> A(K), B(K);
    for (auto& x: A) {
        std::cin >> x.x;
    }
    for (auto& x: B) {
        std::cin >> x.x;
    }
    const auto next = [&](const Vec<SemiRing>& vec) {
        Vec<SemiRing> ret(K, SemiRing::zero());
        ret[0] = vec[K - 1] * B[0];
        for (auto i: rep(0, K - 1)) {
            ret[i + 1] = vec[i] + vec[K - 1] * B[i + 1];
        }
        return ret;
    };
    const auto dbl = [&](const Vec<SemiRing>& vec) {
        Vec<Vec<SemiRing>> coeff(K, Vec<SemiRing>(K, SemiRing::zero()));
        coeff[0] = vec;
        for (auto i: rep(0, K - 1)) {
            coeff[i + 1] = next(coeff[i]);
        }
        Vec<SemiRing> ret(K, SemiRing::zero());
        for (auto i: rep(0, K)) {
            for (auto j: rep(0, K)) {
                ret[i] = ret[i] + coeff[0][j] * coeff[j][i];
            }
        }
        return ret;
    };
    // C(K, *) = B
    // C(0, *) = { 1, 0, 0, ..., 0 }
    Vec<SemiRing> coeff(K, SemiRing::zero());
    coeff[0] = SemiRing::one();
    for (auto d: revrep(0, 64)) {
        coeff = dbl(coeff);
        if (N >> d & 1) {
            coeff = next(coeff);
        }
    }
    SemiRing ans = SemiRing::zero();
    for (auto i: rep(0, K)) {
        ans = ans + A[i] * coeff[i];
    }
    std::cout << ans.x << '\n';
    return;
}

int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);
    H_main(); 
    return 0;
}
0