AT_abc249_f [ABC249F] Ignore Operations
问题分析
给定一个操作序列,你的目标是通过执行这些操作来最大化最终的 \(x\) 值。操作有两种类型:
- 一操作:将 \(x\) 设为某个给定值 \(y\),即 \(x \leftarrow y\)。
- 二操作:将 \(x\) 增加一个给定值 \(y\),即 \(x \leftarrow x + y\)。
同时可以删除最多 \(k\) 个操作。最大化最后得到的 \(x\) 值。
策略
考虑贪心和分类讨论:
- 从右到左处理操作,可以避免重复计算。我们从最后一个操作开始,逐步分析每个操作的影响,并决定是否删除。
- 使用堆来存储所有负数加法操作,以便我们能够选择删除对结果影响最大的负数加法操作。
主要步骤
从后往前遍历操作:
- 对于类型一操作,直接更新 \(ans\) 的最大值。
- 对于类型二操作,若是负数,则加入最大堆。
- 对于类型二操作,若是正数,则加到当前的 \(sum\),毕竟能不删且还是正数肯定是要的。
- 在堆中的元素数量超过 \(k\) 时,弹出堆顶元素,更新 \(sum\)。
CODE
#include<bits/stdc++.h>
#define wk(x) write(x),putchar(' ')
#define wh(x) write(x),putchar('\n')
#define ll long long
#define N 200005
using namespace std;
ll n,m,k,jk,ans,sum,num,cnt,tot;
ll head[N],dis[N],vis[N],wis[N],f[N];
void read(ll &x) {
x = 0;
ll ff = 1;
char ty;
ty = getchar();
while (!(ty >= '0' && ty <= '9')) {
if (ty == '-') ff = -1;
ty = getchar();
}
while (ty >= '0' && ty <= '9')
x = (x << 3) + (x << 1) + ty - '0', ty = getchar();
x *= ff;
return;
}
void write(ll x) {
if (x == 0) {
putchar('0');
return;
}
if (x < 0) {
x = -x;
putchar('-');
}
char asd[201];
ll ip = 0;
while (x) asd[++ip] = x % 10 + '0', x /= 10;
for (ll i = ip; i >= 1; i--) putchar(asd[i]);
return;
}
priority_queue<ll> q;
struct P {
ll x, y;
} v[N];
int main() {
read(n), read(m);
sum = 0;
ans = -1e18;
v[0].x = 1;
for (ll i = 1; i <= n; i++) read(v[i].x), read(v[i].y);
for (ll i = n; i >= 1 && m >= 0; i--) {
if (v[i].x == 1) ans = max(ans, sum + v[i].y), m--;//更新后,因为如果还要往下遍历,所以当前这个点一定要删掉。
else {
if (v[i].y >= 0) sum += v[i].y;//更新。
else q.push(v[i].y);//加入。
}
while (q.size() > m && !q.empty())
sum += q.top(), q.pop();//取出来加入当前最大值里。
}wh(max(ans, sum));
return 0;
}
本文来自博客园,作者:Red_river_hzh,转载请注明原文链接:https://www.cnblogs.com/Red-river-hzh/p/19257071

浙公网安备 33010602011771号