P1792 [国家集训队]种树

P1792 [国家集训队]种树

两个做法WQS二分,或者后悔贪心,这里选择后悔贪心+双向链表。

容易发现如果拿了一个,或者要不拿这个而去拿左右两边的。

答案为 (a_{nxt_i} + a_{pre_i} - a_i) 然后直接贪心。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>

using namespace std;

typedef long long ll;
typedef pair<ll, ll> pll;
const ll MAXN = 1e6+10;

priority_queue <pll> q;
ll N, M, val[MAXN], nxt[MAXN], ans, pre[MAXN], vis[MAXN];

void del(ll);

int main() {
    scanf("%lld%lld", &N, &M);
    if (N == 1 && M == 1) {
    	scanf("%lld", &ans);
    	printf("%lld
", ans);
    	return 0;	
    }
    if (N / 2 < M) {
		puts("Error!");
		return 0;
	}
    for (ll i = 1; i <= N; i++)
        scanf("%lld", val+i);
    for (ll i = 1; i <= N; i++)
        pre[i] = i-1, nxt[i] = i+1, q.push(make_pair(val[i], i)); pre[1] = N, nxt[N] = 1;
    for (ll i = 1; i <= M; i++) {
        while (vis[q.top().second]) q.pop();
        ll now = q.top().second; q.pop();
        ans += val[now];
        val[now] = val[pre[now]] + val[nxt[now]] - val[now];
        del(pre[now]); del(nxt[now]);
        q.push(make_pair(val[now], now));
    }
    printf("%lld
", ans);
    return 0;
}

void del(ll pos) {
    vis[pos] = 1;
    ll l = pre[pos], r = nxt[pos];
    pre[pos] = nxt[pos] = 0;
    nxt[l] = r, pre[r] = l;
}
原文地址:https://www.cnblogs.com/Gensokyo-Alice/p/13904619.html