AT_abc249_f [ABC249F] Ignore Operations

问题分析

给定一个操作序列,你的目标是通过执行这些操作来最大化最终的 \(x\) 值。操作有两种类型:

  1. 一操作:将 \(x\) 设为某个给定值 \(y\),即 \(x \leftarrow y\)
  2. 二操作:将 \(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;
}
posted @ 2025-11-22 16:22  Red_river_hzh  阅读(8)  评论(0)    收藏  举报