专栏文章
题解:CF721D Maxim and Array
CF721D题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mip8f5zy
- 此快照首次捕获于
- 2025/12/03 07:51 3 个月前
- 此快照最后确认于
- 2025/12/03 07:51 3 个月前
前言
当然是讲一下悲惨事迹。
一道绿题调了两个半小时,发动了博主4个人的人脉,最终下课前一分钟调出来。
不就两个半小时嘛 你笑个屁。
特别鸣谢
eddie08012025
austin0116
prettycai666
louis_lxy
思路
首先考虑到贪心。
那么贪心策略是什么呢?
假设 为所有数中最小的,会有以下几种情况:
- 当总和能变为负数,则变为负数,剩下的次数都用来使每个数的绝对值变得平均,且绝对值需要变大。
- 当 只能变为 ,就把 变为 ,不做其他操作(想也操作不了啊)。
- 当 只能是正数,就把 变到最小。
接着考虑怎么做。
和 很好想,就是找到最小值 ,把它修改了再输出即可。
问题就转化为了解决问题 ,那么要如何维护每次更新完的的最小值呢?
我们可以想到优先队列,堆,set 等等。
我这里用 set 来维护绝对不是不会写优先队列。
提醒:记得用 multiset,防止被 set 去重了。
不过好像同学的 set 也能过?数据太水了?
其实不是的,如果你用 set,要重载运算符(operator)。
代码
码风太烂了勿喷。
CPP#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[200005];
int cnt;
struct node{
int x,y;
inline bool operator < (const node &o) const{
if(abs(x)!=abs(o.x))return abs(x)<abs(o.x);
return y<o.y;
}
};
multiset<node>st;
main(){
int n,k,x;
cin>>n>>k>>x;
int mn=2e18,ii=1;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]<0)cnt++;
if(abs(a[i])<mn){
ii=i;
mn=abs(a[i]);
}
}
if(mn-k*x>0){
a[ii]-=k*x;
for(int i=1;i<=n;i++)cout<<a[i]<<" ";
}else if(mn-k*x==0){
a[ii]=0;
for(int i=1;i<=n;i++)cout<<a[i]<<" ";
}else{
if(cnt%2==0){
int c=a[ii];
while(mn>=0){
k--;
mn-=x;
if(c>=0)a[ii]-=x;
else a[ii]+=x;
}
}
for(int i=1;i<=n;i++){
st.insert({a[i],i});
}
for(int i=1;i<=k;i++){
node p=*st.begin();
st.erase(st.begin());
if(p.x<0)p.x-=x;
else p.x+=x;
st.insert(p);
}
for(node p:st){
a[p.y]=p.x;
}
for(int i=1;i<=n;i++){
cout<<a[i]<<" ";
}
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...