368 字
2 分钟
就
【背景描述】
一排 N 个数, 第 i 个数是 Ai , 你要找出 K 个不相邻的数, 使得他们的和最大。 请求出这个最大和。
【输入格式】
第一行两个整数 N 和 K。 接下来一行 N 个整数, 第 i 个整数表示 Ai 。
【输出格式】
一行一个整数表示最大和, 请注意答案可能会超过 int 范围
【样例输入】
3 2
4 5 3
【样例输出】
7
【数据范围】
对于 20% 的数据, N, K ≤ 20 。 对于 40% 的数据, N, K ≤ 1000 。 对于 60% 的数据, N, K ≤ 10000 。 对于 100% 的数据, N, K ≤ 100000 , 1 ≤ Ai ≤ 1000000000。
题解
贪心,每次用一个堆维护最大值 每次都找最大的和他两边的合并,其实是一个可反悔的贪心
主要边界处理
#include <cstdio>#include <cstring>#include <algorithm>#include <set>#include <list>
using namespace std;
#define LL long long
struct data{ LL Num; int pos; bool operator<(const data &a) const { return Num == a.Num ? pos < a.pos : Num > a.Num; }};
set<data> st;
LL a[100005];int nex[100005], fre[100005];
LL Merge(){ int A = st.begin()->pos; LL ans = a[A]; a[A] = -a[A]; a[A] += a[fre[A]], a[A] += a[nex[A]]; st.erase(st.begin()); st.erase((data){a[fre[A]], fre[A]}); st.erase((data){a[nex[A]], nex[A]}); st.insert((data){a[A], A}); if (fre[fre[A]]) nex[fre[fre[A]]] = A; if (nex[nex[A]]) fre[nex[nex[A]]] = A; fre[A] = fre[fre[A]]; nex[A] = nex[nex[A]]; return ans;}int main(){ int n, k; scanf("%d%d", &n, &k); for (int i = 1; i <= n; i++) { scanf("%lld", &a[i]); fre[i] = i - 1; nex[i] = i + 1; st.insert((data){a[i], i}); } nex[n] = 0; a[0] = 0x8080808080808080ll; LL ans = 0; while (k--) { ans += Merge(); } printf("%lld", ans);}