Luogu P1792 [national training team] planting trees (chain table greedy)

Keywords: C++

meaning of the title

Title Link

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
*/

Posted by heltr on Mon, 02 Dec 2019 08:40:53 -0800