D2. Red-Blue Operations (Hard Version)
题意
给定一个长度为
的数列和 次询问,初始所有数的颜色都是红色,每次询问给一个 ,要求你做恰好 次操作,对于第 次操作,你可以任选数列中的一个数
- 如果它是红色,则将它的值加上
,并将它变成蓝色 - 如果它是蓝色,则将它的值减去
,并将它变为红色 对于每个询问,求
次操作后数列最小值的最大值, , ,
题解
如果
如果
我们不妨先考虑
首先证明这
证明:我们交换序列中的任一对
现在我们考虑这些操作分配给了哪些数,对于目前的最优序列,可以将
之前已经说明,如果
证明:考虑减法操作结束后,答案为
所以,答案为
首先考虑
显然
求新数列的和,通过求和公式,显然也可以做到
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF = 1e18;
const int N = 2e5 + 7;
ll n, q, sum, a[N], mi[N];
ll solve(ll k) {
if (k <= n) {
return min(mi[k] + k, a[k + 1]);
}
else if ((k - n) % 2) {
ll op = (k - n + 1) / 2, presum = (k - n + 2 + k) * (n - 1) / 2;
return min(min(mi[n - 1] + k, a[n]), (sum + presum - op) / n);
}
else {
ll op = (k - n) / 2, presum = (k - n + 1 + k) * n / 2;
return min(mi[n] + k, (sum + presum - op) / n);
}
}
int main() {
scanf("%lld%lld", &n, &q);
for (ll i = 1; i <= n; ++i) {
scanf("%lld", &a[i]);
sum += a[i];
}
sort(a + 1, a + 1 + n);
a[n + 1] = mi[0] = INF;
for (ll i = 1; i <= n; ++i) {
mi[i] = min(mi[i - 1], a[i] - i + 1);
}
while (q--) {
ll k;
scanf("%lld", &k);
printf("%lld ", solve(k));
}
return 0;
}
分类:
ACM题解及知识点总结
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧