meaning of the title
Sol
The most intuitive way is wqs dichotomy + dp. However, there is also a kind of greedy practice.
It's not hard to think that we can mark the left and right sides according to the weight from big to small, but this is obviously wrong, such as \ (1 \ 231 \ 233 \ 232 \). We will get \ (234 \) instead of \ (463 \). Consider adding a mechanism of estoppel, that is, we can add a decision to cancel the influence of the decision and add the contribution of a new decision.
Consider this approach: change the original point weight to \ (231 + 232 - 233 \), and use the two-way linked list to maintain the predecessor and successor. Change the precursor of \ (233 \) to the precursor of \ (231 \) and the successor of \ (233 \) to the successor of \ (232 \). In this way, when we select the contribution of this point again, it is equivalent to selecting \ (231 + 232 \)
Complexity \ (O(nlogn) \)
// luogu-judger-enable-o2 #include<bits/stdc++.h> #define Pair pair<int, int> #define MP(x, y) make_pair(x, y) #define fi first #define se second #define LL long long #define ull unsigned long long #define Fin(x) {freopen(#x".in","r",stdin);} #define Fout(x) {freopen(#x".out","w",stdout);} using namespace std; const int MAXN = 1e6 + 10, mod = 1e9 + 7, INF = 1e9 + 10; const double eps = 1e-9; template <typename A, typename B> inline bool chmin(A &a, B b){if(a > b) {a = b; return 1;} return 0;} template <typename A, typename B> inline bool chmax(A &a, B b){if(a < b) {a = b; return 1;} return 0;} template <typename A, typename B> inline LL add(A x, B y) {if(x + y < 0) return x + y + mod; return x + y >= mod ? x + y - mod : x + y;} template <typename A, typename B> inline void add2(A &x, B y) {if(x + y < 0) x = x + y + mod; else x = (x + y >= mod ? x + y - mod : x + y);} template <typename A, typename B> inline LL mul(A x, B y) {return 1ll * x * y % mod;} template <typename A, typename B> inline void mul2(A &x, B y) {x = (1ll * x * y % mod + mod) % mod;} template <typename A> inline void debug(A a){cout << a << '\n';} template <typename A> inline LL sqr(A x){return 1ll * x * x;} inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int N, M, a[MAXN], pre[MAXN], nxt[MAXN], vis[MAXN], cnt; priority_queue<Pair> q; signed main() { N = read(); M = read(); if(M > N / 2) {puts("Error!"); return 0;} for(int i = 1; i <= N; i++) a[i] = read(), pre[i] = i - 1, nxt[i] = i + 1, q.push({a[i], i}); pre[1] = N; nxt[N] = 1; int ans = 0; while(M--) { Pair p = q.top(); q.pop(); int c = p.se; if( vis[c]) {M++; continue;} ans += p.fi; a[c] = a[pre[c]] + a[nxt[c]] - a[c]; vis[pre[c]] = 1; vis[nxt[c]] = 1; pre[c] = pre[pre[c]]; nxt[c] = nxt[nxt[c]]; nxt[pre[c]] = c; pre[nxt[c]] = c; q.push({a[c], c}); } cout << ans; return 0; } /* 2 1 1 */