题意
给定 \(n\) 个点,初始在 \(s\) 点,求走遍所有点的最小移动距离,以及方案,需要向左走恰好 \(l\) 次。
\(n \le 10 ^ 5\)。
Sol
难点在于想到枚举终点。
钦定当前若终点在起点右边,那么最优走法就是先向左走到底,然后向右走到底,然后最后再走到终点。
其中中间重复走的段,显然可以发现每一段至多被多走一次,用来多一个 \(l\) 少一个 \(r\),如果一段走了多次,还不如直接重复走旁边的两段。
对于两边本身就走两次的段,尽量全部走 \(l\),这样可以算出来中间需要多走多少次,注意到每次需要的次数是单调不降的,直接对顶堆维护即可。
求方案略显恶心,复杂度:\(O(n \log n)\)。
Code
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <array>
#include <queue>
#include <set>
#include <vector>
#define ll long long
using namespace std;
#ifdef ONLINE_JUDGE#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
char buf[1 << 23], *p1 = buf, *p2 = buf, ubuf[1 << 23], *u = ubuf;#endif
int read() {int p = 0, flg = 1;char c = getchar();while (c < '0' || c > '9') {if (c == '-') flg = -1;c = getchar();}while (c >= '0' && c <= '9') {p = p * 10 + c - '0';c = getchar();}return p * flg;
}
void write(ll x) {if (x < 0) {x = -x;putchar('-');}if (x > 9) {write(x / 10);}putchar(x % 10 + '0');
}
bool _stmer;const int N = 1e5 + 5;namespace Hth {priority_queue <int> q1;
priority_queue <int, vector <int>, greater <int> > q2;ll ans;void insert(int x) { q2.push(x); }int resize(int k) {while (q1.size() > k)ans -= q1.top(), q2.push(q1.top()), q1.pop();while (q1.size() < k && q2.size())ans += q2.top(), q1.push(q2.top()), q2.pop();return q1.size() == k;
}void init() {while (q1.size()) q1.pop();while (q2.size()) q2.pop();ans = 0;
}} //Htharray <int, N> s;vector <ll> solve(int n, int m, int k) {Hth::init();ll ans = 0, res = 2e18;for (int i = k + 1; i <= n; i++) {ll _res = 2e18;if (k - 1 + n - i >= m)_res = 2 * s[n] - s[i] + s[k];else if (Hth::resize(m - k - n + i + 1))_res = 2 * s[n] - s[i] + s[k] + 2ll * Hth::ans;/* if (i == 10) *//* cerr << m - k - n + i + 1 << " " << Hth::ans << " " << _res << "@@@@" << endl; */if (_res < res) res = _res, ans = i;if (i - 1 > k) Hth::insert(s[i] - s[i - 1]);}if (!ans) return vector <ll>(1, res);Hth::init();for (int i = k + 2; i < ans; i++)Hth::insert(s[i] - s[i - 1]);Hth::resize(m - k - n + ans + 1);/* cerr << m - k - n + ans + 1 << "@" << endl; */vector <ll> isl; multiset <int> req;isl.push_back(res);while (Hth::q1.size())req.insert(Hth::q1.top()), Hth::q1.pop();int tp0 = 0;for (int i = k - 1; i >= 2; i--)if (m > (k != 1) + (ans != n)) isl.push_back(i), m--, tp0++;if (k != 1) isl.push_back(1), m--;for (int i = 2; i <= k - tp0 - 1; i++)isl.push_back(i);set <int> tp;for (int i = k + 1; i < ans - 1; i++)if (i + 1 != ans && req.find(s[i + 1] - s[i]) != req.end() && m > (ans != n))tp.insert(i), req.erase(req.find(s[i + 1] - s[i])), m--;/* for (auto p : tp) *//* cerr << p << "@" << endl; */for (int i = k + 1; i <= ans - 1; i++) {/* if (i + 1 != ans && m > 1 && req.find(s[i + 1] - s[i]) != req.end()) *//* isl.push_back(i + 1), isl.push_back(i), m--, req.erase(req.find(s[i + 1] - s[i])), i += 2; *//* else *//* isl.push_back(i); */int lst = 0;while (tp.find(i + lst) != tp.end()) lst++;if (!lst) isl.push_back(i);else {for (int j = lst + i; j >= i; j--)isl.push_back(j);i += lst;/* isl.push_back(-1); */}}for (int i = ans + 1; i <= ans + (n - ans - 1) - (m - (ans != n)); i++)isl.push_back(i);if (ans != n) isl.push_back(n);for (int i = n - 1; i >= n - (m - (ans != n)); i--)isl.push_back(i);isl.push_back(ans);return isl;
}bool _edmer;
int main() {cerr << (&_stmer - &_edmer) / 1024.0 / 1024.0 << "MB\n";int n = read(), m = read(), k = read();for (int i = 1; i <= n; i++) s[i] = read();if (m == 0) {if (k != 1) return puts("-1"), 0;write(s[n] - s[1]), puts("");for (int i = 2; i <= n; i++)write(i), putchar(32);return puts(""), 0;}if (m == n - 1) {if (k != n) return puts("-1"), 0;write(s[n] - s[1]), puts("");for (int i = n - 1; i; i--)write(i), putchar(32);return puts(""), 0;}vector <ll> tp1 = solve(n, m, k);m = n - 1 - m, k = n - k + 1;for (int i = 1; i <= n; i++)s[i] = s[n] - s[i];reverse(s.begin() + 1, s.begin() + 1 + n);/* for (int i = 1; i <= n; i++) *//* cerr << s[i] << " "; *//* cerr << endl; */vector <ll> tp2 = solve(n, m, k);if (tp1.front() < tp2.front()) {write(tp1.front()), puts("");tp1.erase(tp1.begin());for (auto p : tp1)write(p), putchar(32);puts("");}else {write(tp2.front()), puts("");tp2.erase(tp2.begin());for (auto p : tp2)write(n - p + 1), putchar(32);/* cerr << p << " "; */puts("");}/* cerr << tp.front() << endl; *//* for (auto k : tp) *//* cerr << k << " "; *//* cerr << endl; */return 0;
}