제출 #1355188

#제출 시각아이디문제언어결과실행 시간메모리
1355188Trisanu_DasRotating Lines (APIO25_rotate)C++20
컴파일 에러
0 ms0 KiB
#include <bits/stdc++.h>
using namespace std;

const int L = 50000;

struct BIT {
    vector<int> cnt;
    vector<long long> sum;
    int n;
    BIT(int sz) : n(sz), cnt(sz+1, 0), sum(sz+1, 0) {}
    void add(int idx, int val) {
        idx++; // 1-based
        while (idx <= n) {
            cnt[idx] += val;
            sum[idx] += val * (idx-1);
            idx += idx & -idx;
        }
    }
    int query_cnt(int idx) {
        if (idx < 0) return 0;
        idx = min(idx, n-1);
        idx++;
        int res = 0;
        while (idx > 0) { res += cnt[idx]; idx -= idx & -idx; }
        return res;
    }
    long long query_sum(int idx) {
        if (idx < 0) return 0;
        idx = min(idx, n-1);
        idx++;
        long long res = 0;
        while (idx > 0) { res += sum[idx]; idx -= idx & -idx; }
        return res;
    }
    int range_cnt(int l, int r) {
        if (l <= r) return query_cnt(r) - query_cnt(l-1);
        else return query_cnt(L-1) - query_cnt(l-1) + query_cnt(r);
    }
    long long range_sum(int l, int r) {
        if (l <= r) return query_sum(r) - query_sum(l-1);
        else return query_sum(L-1) - query_sum(l-1) + query_sum(r);
    }
};

double acute_sum(int x, BIT& bit) {
    int l1 = x;
    int r1 = (x + L/2 - 1) % L;
    int cnt1 = bit.range_cnt(l1, r1);
    long long sum1 = bit.range_sum(l1, r1);
    long long contrib1 = sum1 - (long long)cnt1 * x;

    int l2 = (x + L/2) % L;
    int r2 = (x + L - 1) % L;
    int cnt2 = bit.range_cnt(l2, r2);
    long long sum2 = bit.range_sum(l2, r2);
    long long contrib2 = (long long)cnt2 * (L + x) - sum2; // L - (y - x) = L + x - y

    return contrib1 + contrib2;
}

void energy(int n, std::vector<int> v) {
    vector<int> cur = v;
    BIT bit(L);
    for (int val : v) bit.add(val, 1);

    vector<int> cnt(L, 0);
    for (int val : v) cnt[val]++;
    set<int> pts;
    for (int i = 0; i < L; i++) if (cnt[i]) pts.insert(i);

    auto gap_len = [&](int a, int b) {
        return (b - a + L) % L;
    };

    using Gap = pair<int, int>;
    priority_queue<Gap> max_gap;
    priority_queue<Gap, vector<Gap>, greater<Gap>> min_gap;

    auto update_gaps = [&]() {
        // clear queues (lazy deletion will be used)
        while (!max_gap.empty()) max_gap.pop();
        while (!min_gap.empty()) min_gap.pop();
        if (pts.size() <= 1) return;
        for (auto it = pts.begin(); it != pts.end(); ++it) {
            int a = *it;
            auto nit = next(it);
            if (nit == pts.end()) nit = pts.begin();
            int b = *nit;
            int len = gap_len(a, b);
            max_gap.emplace(len, a);
            min_gap.emplace(len, a);
        }
    };

    update_gaps();

    vector<vector<int>> rods_at(L);
    for (int i = 0; i < n; i++) rods_at[cur[i]].push_back(i);

    // function to try moving a rod from old_pos to new_pos
    auto try_move = [&](int rod_idx, int old_pos, int new_pos) -> bool {
        if (old_pos == new_pos) return false;
        double old_contrib = acute_sum(old_pos, bit);
        double new_contrib = acute_sum(new_pos, bit) - min(abs(new_pos - old_pos), L - abs(new_pos - old_pos));
        double delta = new_contrib - old_contrib;
        if (delta > 1e-9) {
            rotate(vector<int>{rod_idx}, (new_pos - old_pos + L) % L);
            // update data structures
            bit.add(old_pos, -1);
            bit.add(new_pos, 1);
            cnt[old_pos]--;
            if (cnt[old_pos] == 0) pts.erase(old_pos);
            cnt[new_pos]++;
            if (cnt[new_pos] == 1) pts.insert(new_pos);
            // update rods_at
            auto& vec_old = rods_at[old_pos];
            vec_old.erase(remove(vec_old.begin(), vec_old.end(), rod_idx), vec_old.end());
            rods_at[new_pos].push_back(rod_idx);
            cur[rod_idx] = new_pos;
            update_gaps();
            return true;
        }
        return false;
    };

    const int MAX_ITER = 2000000 / n + 10; // each move costs 1 selection
    for (int iter = 0; iter < MAX_ITER; ++iter) {
        if (pts.size() <= 1) break;
        // get largest gap
        while (!max_gap.empty()) {
            auto [len, a] = max_gap.top();
            auto it = pts.find(a);
            if (it == pts.end()) { max_gap.pop(); continue; }
            auto nit = next(it); if (nit == pts.end()) nit = pts.begin();
            int b = *nit;
            if (gap_len(a, b) != len) { max_gap.pop(); continue; }
            break;
        }
        if (max_gap.empty()) break;
        auto [max_len, max_left] = max_gap.top();

        while (!min_gap.empty()) {
            auto [len, a] = min_gap.top();
            auto it = pts.find(a);
            if (it == pts.end()) { min_gap.pop(); continue; }
            auto nit = next(it); if (nit == pts.end()) nit = pts.begin();
            int b = *nit;
            if (gap_len(a, b) != len) { min_gap.pop(); continue; }
            break;
        }
        if (min_gap.empty()) break;
        auto [min_len, min_left] = min_gap.top();

        if (max_len - min_len <= 1) break; // close enough

        int rod_pos = min_left;
        if (rods_at[rod_pos].empty()) {
            // try the right endpoint
            auto it = pts.find(min_left);
            auto nit = next(it); if (nit == pts.end()) nit = pts.begin();
            rod_pos = *nit;
            if (rods_at[rod_pos].empty()) continue; // shouldn't happen
        }
        int rod_idx = rods_at[rod_pos].back(); // pick one rod

        auto it_max = pts.find(max_left);
        auto nit_max = next(it_max); if (nit_max == pts.end()) nit_max = pts.begin();
        int max_right = *nit_max;
        int gap_start = max_left;
        int gap_len_val = max_len;
        vector<int> candidates;
        candidates.push_back((gap_start + gap_len_val / 2) % L);
        if (gap_len_val > 2) {
            candidates.push_back((gap_start + gap_len_val / 4) % L);
            candidates.push_back((gap_start + 3 * gap_len_val / 4) % L);
        }

        bool moved = false;
        for (int new_pos : candidates) {
            if (try_move(rod_idx, rod_pos, new_pos)) {
                moved = true;
                break;
            }
        }
        if (!moved) {
            int flip_pos = (rod_pos + 25000) % L;
            if (try_move(rod_idx, rod_pos, flip_pos)) {
                moved = true;
            }
        }
        if (!moved) {
            break;
        }
    }
}

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

rotate.cpp: In lambda function:
rotate.cpp:107:19: error: no matching function for call to 'rotate(std::vector<int>, int)'
  107 |             rotate(vector<int>{rod_idx}, (new_pos - old_pos + L) % L);
      |             ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/13/algorithm:61,
                 from /usr/include/x86_64-linux-gnu/c++/13/bits/stdc++.h:51,
                 from rotate.cpp:1:
/usr/include/c++/13/bits/stl_algo.h:1390:5: note: candidate: 'template<class _FIter> constexpr _FIter std::_V2::rotate(_FIter, _FIter, _FIter)'
 1390 |     rotate(_ForwardIterator __first, _ForwardIterator __middle,
      |     ^~~~~~
/usr/include/c++/13/bits/stl_algo.h:1390:5: note:   template argument deduction/substitution failed:
rotate.cpp:107:19: note:   deduced conflicting types for parameter '_FIter' ('std::vector<int>' and 'int')
  107 |             rotate(vector<int>{rod_idx}, (new_pos - old_pos + L) % L);
      |             ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/13/algorithm:73:
/usr/include/c++/13/pstl/glue_algorithm_defs.h:260:1: note: candidate: 'template<class _ExecutionPolicy, class _ForwardIterator> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> std::rotate(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _ForwardIterator)'
  260 | rotate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last);
      | ^~~~~~
/usr/include/c++/13/pstl/glue_algorithm_defs.h:260:1: note:   template argument deduction/substitution failed:
rotate.cpp:107:19: note:   candidate expects 4 arguments, 2 provided
  107 |             rotate(vector<int>{rod_idx}, (new_pos - old_pos + L) % L);
      |             ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~