OJ练习之加减(中等偏难)
加减题号NC224938时间限制C/C/Rust/Pascal 1秒其他语言2秒空间限制C/C/Rust/Pascal 256 M其他语言512 M64bit IO Format: %lld题目描述小红拿到了一个长度为 n 的数组。她每次操作可以让某个数加 1 或者某个数减 1 。小红最多能进行 k 次操作。她希望操作结束后该数组出现次数最多的元素次数尽可能多。你能求出这个最大的次数吗输入描述:第一行两个正整数 n 和 k 第二行有 n 个正整数 ai 1≤n≤10^5 1≤k≤10^12 1≤ai≤10^9输出描述:不超过 k 次操作之后数组中可能出现最多次数元素的次数。示例1输入5 3 6 3 20 8 1输出2说明共 3 次操作如下 第一个数加一。 第二个数加一。 第四个数减一。 数组变成了 7 4 20 7 1 共有 2 个相同的数 7 。 可以证明 2 为最优解。另外此上操作并不是唯一的操作。题解前缀和滑动窗口贪心#includeiostream#includealgorithmusingnamespacestd;// k已经超出了int的范围ai涉及到加减操作很容易超出int范围所以直接使用long longtypedeflonglongLL;constintN1e510;LL n,k;LL arr[N];LL sum[N];LLcal(intleft,intright){// 选取区间内中间下标对于区间内偶数个来说选中间两个的任意一个结果都一样intmid(leftright)/2;// 区间内mid左边的个数×a[mid]-mid左边的和mid右边和和 - mid右边的个数×a[mid]return(mid-left)*arr[mid]-(sum[mid-1]-sum[left-1])(sum[right]-sum[mid])-(right-mid)*arr[mid];// 根据规律总结出的公示可以直接O(1)出结果}intmain(){cinnk;// 将n个数存入从下标1开始存入for(inti1;in;i)cinarr[i];// 将n个数按照从小到大排序sort(arr1,arr1n);// 将前i个数的和按照对应下标存入sum数组里备用for(inti1;in;i)sum[i]sum[i-1]arr[i];intleft1,right1;intret1;// 根据题意ret最小也是1while(rightn){// cal用来获取将区间所有数都变成同一个数的最小加减次数即最小代价LL costcal(left,right);while(costk)// 如果最小代价比规定的都大继续寻找更小的可能{left;// 再扩大区间代价还会增大要让left右移costcal(left,right);}// 更新retretmax(ret,right-left1);// 当然选择满足的区间差值最大的right;// 继续尝试寻找更优解}coutretendl;return0;}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2535488.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!