Codeforces Round #474-B(贪心)
一、题目链接
http://codeforces.com/contest/960/problem/B
二、题意
给定三个数字$N, k1, k2$,接下来给出两组数$a[]$和$b[]$,每组数$N$个,对$a$组数操作$k1$次,对$b$组数操作$k2$次,每次操作都可以从指定的数组中选择任意一个数加$1$或减$1$。求操作完$k1$和$k2$之后,最小的差分平方和$\sum\limits_{i=1}^{N}(a_i - b_i)^2$。
三、思路
其实思路很简单,只是当时时间比较晚了,几乎精疲力竭,导致脑子一片浆糊。
假设差分数组为$c[]$,$c_i = a_i - b_i$,每次从$c[]$中选出绝对值最大的数,那么,考虑$a_i$和$b_i$的大小关系,同时,再考虑$k1$和$k2$的大小关系。目的都是使两个数($a_i$和$b_i$)的差距尽可能小。那么,如果$k1<k2$,优先操作$a[]$,否则优先操作$b[]$。这里的逻辑在代码中非常明显,不过多解释。
关键是这一点:$a[]$和$b[]$全相等时的情况。
(1)如果$k1>0$且$k2>0$,那么这时正确的做法不是把$k1$均分到$a[]$上,把$k2$均分到$b[]$上。而是,反复对某一个数加$1$减$1$。那么,这样的话,最后的结果,最多就是$1$,否则就是$0$,这比均分更优。易知,在这种情况下,结果为$1$的条件是$k1$和$k2$奇偶相异。
(2)如果$k1$或$k2$中某一个大于$0$,做法和上面的一样。
(3)否则,必定$k1\ =\ 0$且$k2\ =\ 0$。(其实这从if-elseif-else结构也可以推出来了)。
(4)不可能出现$k1$和$k2$其中某一个大于$0$或两个都大于$0$而且$\exists_i, 1 \le i \le N, a[i] \ne b[i]$的情况。想想便知,如果存在某个差分$a_i - b_i \ne 0$,且$k1$和$k2$其中某一个大于$0$或两个都大于$0$,那为何不使他们靠的更近一些呢,这不是更好吗,是吧。
其实上面的逻辑感觉还挺麻烦的。参考了一个下rank1的代码,思路、代码都非常清晰简洁。直接记录差分数组$c_i = a_i - b_i$,计算出总的可操作次数。然后每次从$\left\|c_i\right\|$中选出一个最大的数$c_i$,如果$c_i>0$,那么,$c_i--$,否则$c_i++$。同时,总的可操作次数减$1$。当操作次数用完的时候,计算答案即可。妙!!!当数组$c[]$全为$0$时,只要总操作次数大于$0$,它肯定会选一个$c_i$减$1$,下次它肯定会被再次选出来加$1$。这样,这个$c_i$就被反复的加$1$减$1$了。非常巧妙!!!
这题没必要优先队列优化,直接暴力写就好了。还没这么麻烦。
四、代码实现
#include<bits/stdc++.h> using namespace std; #define pb(x) push_back(x) #define mk(x, y) make_pair(x, y) #define pln() putchar('\n') #define cln() (cout << '\n') typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; ; template <class T> inline void read(T &x) { int t; bool flag = false; ')) ; '; + t - '; if(flag) x = -x; } int N, K1, K2; int a[MAXN], b[MAXN]; LL sol2() { || K2 > ) { , pos = -; ; i <= N; ++i) { if(abs(a[i] - b[i]) > t1) { t1 = abs(a[i] - b[i]); pos = i; } } )break; if(a[pos] < b[pos]) { && K1 >= K2)a[pos]++, K1--; && K1 < K2)b[pos]--, K2--; } else if(a[pos] > b[pos]) { && K1 >= K2)a[pos]--, K1--; && K1 < K2)b[pos]++, K2--; } } bool eq = true; ;i <= N && eq;++i)eq = a[i] == b[i]; ) ^ (K2 & ); LL ans = ; ; i <= N; ++i)ans += LL(a[i] - b[i]) * LL(a[i] - b[i]); return ans; } int main() { #ifndef ONLINE_JUDGE freopen("input.txt", "r", stdin); freopen("output2.txt", "w", stdout); #endif // ONLINE_JUDGE while(~scanf("%d%d%d", &N, &K1, &K2)) { ; i <= N; ++i)read(a[i]); ; i <= N; ++i)read(b[i]); cout << sol2() << endl; } ; }
Codeforces Round #474-B(贪心)的更多相关文章
- codeforces round 474 pathwalks
题目传送门http://codeforces.com/contest/960/problem/F 4月25号期中考,答应过年级组长要考年排前3的,所以25号以前我就不搞竞赛了,期中考要考好. 有很多大 ...
- Divide by Zero 2018 and Codeforces Round #474 (Div. 1 + Div. 2, combined)
思路:把边看成点,然后每条边只能从下面的边转移过来,我们将边按照u为第一关键字,w为第二关键字排序,这样就能用线段树维护啦. #include<bits/stdc++.h> #define ...
- Divide by Zero 2018 and Codeforces Round #474 (Div. 1 + Div. 2, combined)G - Bandit Blues
题意:求满足条件的排列,1:从左往右会遇到a个比当前数大的数,(每次遇到更大的数会更换当前数)2.从右往左会遇到b个比当前数大的数. 题解:1-n的排列,n肯定是从左往右和从右往左的最后一个数. 考虑 ...
- 贪心+模拟 Codeforces Round #288 (Div. 2) C. Anya and Ghosts
题目传送门 /* 贪心 + 模拟:首先,如果蜡烛的燃烧时间小于最少需要点燃的蜡烛数一定是-1(蜡烛是1秒点一支), num[g[i]]记录每个鬼访问时已点燃的蜡烛数,若不够,tmp为还需要的蜡烛数, ...
- 贪心 Codeforces Round #288 (Div. 2) B. Anton and currency you all know
题目传送门 /* 题意:从前面找一个数字和末尾数字调换使得变成偶数且为最大 贪心:考虑两种情况:1. 有偶数且比末尾数字大(flag标记):2. 有偶数但都比末尾数字小(x位置标记) 仿照别人写的,再 ...
- 贪心 Codeforces Round #301 (Div. 2) B. School Marks
题目传送门 /* 贪心:首先要注意,y是中位数的要求:先把其他的都设置为1,那么最多有(n-1)/2个比y小的,cnt记录比y小的个数 num1是输出的1的个数,numy是除此之外的数都为y,此时的n ...
- Codeforces Round #412 (rated, Div. 2, base on VK Cup 2017 Round 3) A B C D 水 模拟 二分 贪心
A. Is it rated? time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...
- 贪心 Codeforces Round #297 (Div. 2) C. Ilya and Sticks
题目传送门 /* 题意:给n个棍子,组成的矩形面积和最大,每根棍子可以-1 贪心:排序后,相邻的进行比较,若可以读入x[p++],然后两两相乘相加就可以了 */ #include <cstdio ...
- 贪心 Codeforces Round #304 (Div. 2) B. Soldier and Badges
题目传送门 /* 题意:问最少增加多少值使变成递增序列 贪心:排序后,每一个值改为前一个值+1,有可能a[i-1] = a[i] + 1,所以要 >= */ #include <cstdi ...
- 贪心 Codeforces Round #303 (Div. 2) B. Equidistant String
题目传送门 /* 题意:找到一个字符串p,使得它和s,t的不同的总个数相同 贪心:假设p与s相同,奇偶变换赋值,当是偶数,则有答案 */ #include <cstdio> #includ ...
随机推荐
- Maximum Depth of Binary Tree,求树的最大深度
算法分析:求树的最小最大深度时候,都有两种方法,第一种是递归思想.树最大最小深度,即为它的子树的最大最小深度+1,是动态规划的思想.还有一种方法是层序遍历树,只不过求最小深度时,找到第一个叶子节点就可 ...
- 常用 Math 属性及方法
Math 对象 Math.PI π 3.141592653589793 Math.ceil('2.5') Math.ceil(2.1) 向上取整 3 Math.floor ...
- 两个cookie的合并
这里为什么会想到这个问题呢? 1.我们在对一个商品下订单之前需要2个步骤,1---登录,2---加入购物车 2.那么我们到底是用哪一个cookie呢?实际测试的时候, a.发现只用了登录cookie, ...
- Android------实现图片双击放大,缩小,左右滑动的多种方式
项目中常常有图片浏览功能.像微信朋友圈图片浏览,QQ空间照片浏览 的功能. 实现图片双击放大,缩小,左右滑动等效果. 来看看我的效果图,希望能满足你的要求 前三个button按钮是参考网上的多种实 ...
- Python的第一次作业
题目1 : 描述:通过趣味的打怪来学习random随机函数. 代码: from random import * import types choc=0 hs=[100] numer=[randint( ...
- 006PHP文件处理—— 目录操作 删除目录 删除置顶类型文件
<?php /** * 目录操作 删除目录 删除置顶类型文件 */ //echo rmdir('61') or die('目录删除失败'); //删除一个目录中有其他文件的内容的方法: //第1 ...
- 005——php字符串中的处理函数(四)
<?php /** * 字符串处理函数: * parse_url 解析URL.返回其组成部分 */ /* $url="http://www.lantianwang.com/admin/ ...
- bzoj2759
题解: lct+解线性方程组 首先先把每一个环搞出来,然后再建立一个额外的点 然后解方程.. 代码: #include <bits/stdc++.h> using namespace st ...
- Ubuntu 16.04 日常工具
shutter sudo apt-get install shutter indicator-sysmonitor 之前需要通过deb包安装,现在可以通过添加PPA安装: sudo add-apt-r ...
- 解决IE8地址栏没有下拉
装了IE8,但是地址栏没有下拉,下载下面的文件,把两个文件都复制到 系统盘windows/system32,然后cmd下分别执行 regsvr32 chsbrkr.dll regsvr32 chtbr ...