Becoder # 16288. 「BZOJ2288 POJ Challenge」生日礼物
首先我们可以先把点给缩一缩,把连续的正数点和连续的负数点分别缩成一个点,比如 1 2 3 -1 -1 1 2
这个东西我们就可以将其缩成 6 -2 3
我们可以发现,求前者的值等于求后者的值,我们就将原序列变为了正负交替的序列。
然后我们就可以开始反悔贪心,将所有数的点全部丢进小根堆里,小根堆的权值是这个点的绝对值,将所有正数的点暂时全部加进答案
当一个点是负数,而且它在角落,即左右两边有没有的点,那么我们就可以将其抛弃掉不管它了,反之,那么我们可以分类讨论一下:
-
这个点是负数:那么它和它左右两边的点可以是这个形式“正负正”那我们就将这一组合并起来,那正数的点的个数就会减去
答案还得加上这个负点,然后我们在把这个新的点丢进堆里面去。 -
这个点是正点:那么它和它左右两边的点可以是这个形式“负正负”那我们就将这一组合并起来,那正数的点的个数就会减去
答案还得减去上这个正点,然后我们在把这个新的点丢进堆里面去。 -
如果这个点是正点,且在最左边或者最右边:那么可以成这个形式“正负”“负正”,很明显我们还是要将其合并起来,然后减去它,再将新点扔进堆里面去,目前选中的点也减去
。
整理一下我们就可以变为,如果这个点满足:是一个负数,左右两边点不全,我们就删除它。如果不满足:答案减去它的绝对值,个数减
如果还不明白,就结合着代码吧。
#include <queue>
#include <cstring>
#include <algorithm>
#include <iostream>
#define x first
#define y second
using namespace std;
namespace oi{
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using db = double;
using pll = pair<ll, ll>;
#define endl '\n'
inline ll read() {
char ch = getchar(); ll fu = 0, s = 0;
while(!isdigit(ch)) fu |= (ch == '-'), ch = getchar();
while(isdigit(ch)) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
return fu ? -s : s;
}
template <typename T>
inline void write(T x, char ch) {
if(x < 0) putchar('-'), x = -x;
static int stk[30];
int tt = 0;
do stk[++tt] = x % 10, x /= 10; while(x);
while(tt) putchar(stk[tt--] ^ 48);
putchar(ch);
}
template <typename T>
inline void write(T x) {
if(x < 0) putchar('-'), x = -x;
static int stk[30];
int tt = 0;
do stk[++tt] = x % 10, x /= 10; while(x);
while(tt) putchar(stk[tt--] ^ 48);
}
inline void write(char x) {putchar(x);}
};
using namespace oi;
const int MAXN = 1e5 + 10;
int n, a[MAXN], l[MAXN], r[MAXN], m;
int x, cnt;
ll ans;
bool st[MAXN];
void del(int x) {
st[x] = true;
r[l[x]] = r[x];
l[r[x]] = l[x];
}
void solve() {
n = read(), m = read();
for (int i = 1; i <= n; i++) {
x = read(); if (!x) continue;
if (1ll * x * a[cnt] > 0) a[cnt] += x;
else a[++cnt] = x;
}
n = cnt;
cnt = 0;
priority_queue<pii, vector<pii>, greater<pii>> q;
for (int i = 1; i <= n; i++) {
if (a[i] > 0) cnt++, ans += a[i];
l[i] = i - 1, r[i] = i + 1;
q.push({abs(a[i]), i});
}
while (cnt > m) {
while (st[q.top().y]) q.pop();
pii t = q.top(); q.pop();
int x = t.y;
if (l[x] != 0 && r[x] != n + 1 || a[x] > 0) {
cnt--; ans -= abs(a[x]);
a[x] += a[l[x]] + a[r[x]];
del(l[x]), del(r[x]);
q.push({abs(a[x]), x});
} else {
del(x);
}
}
write(ans, '\n');
}
signed main() {
// freopen("test.in", "r", stdin);
// freopen("test.out", "w", stdout);
int T = 1;
// T = read();
while(T--) solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!