一、题目链接

  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(贪心)的更多相关文章

  1. codeforces round 474 pathwalks

    题目传送门http://codeforces.com/contest/960/problem/F 4月25号期中考,答应过年级组长要考年排前3的,所以25号以前我就不搞竞赛了,期中考要考好. 有很多大 ...

  2. Divide by Zero 2018 and Codeforces Round #474 (Div. 1 + Div. 2, combined)

    思路:把边看成点,然后每条边只能从下面的边转移过来,我们将边按照u为第一关键字,w为第二关键字排序,这样就能用线段树维护啦. #include<bits/stdc++.h> #define ...

  3. Divide by Zero 2018 and Codeforces Round #474 (Div. 1 + Div. 2, combined)G - Bandit Blues

    题意:求满足条件的排列,1:从左往右会遇到a个比当前数大的数,(每次遇到更大的数会更换当前数)2.从右往左会遇到b个比当前数大的数. 题解:1-n的排列,n肯定是从左往右和从右往左的最后一个数. 考虑 ...

  4. 贪心+模拟 Codeforces Round #288 (Div. 2) C. Anya and Ghosts

    题目传送门 /* 贪心 + 模拟:首先,如果蜡烛的燃烧时间小于最少需要点燃的蜡烛数一定是-1(蜡烛是1秒点一支), num[g[i]]记录每个鬼访问时已点燃的蜡烛数,若不够,tmp为还需要的蜡烛数, ...

  5. 贪心 Codeforces Round #288 (Div. 2) B. Anton and currency you all know

    题目传送门 /* 题意:从前面找一个数字和末尾数字调换使得变成偶数且为最大 贪心:考虑两种情况:1. 有偶数且比末尾数字大(flag标记):2. 有偶数但都比末尾数字小(x位置标记) 仿照别人写的,再 ...

  6. 贪心 Codeforces Round #301 (Div. 2) B. School Marks

    题目传送门 /* 贪心:首先要注意,y是中位数的要求:先把其他的都设置为1,那么最多有(n-1)/2个比y小的,cnt记录比y小的个数 num1是输出的1的个数,numy是除此之外的数都为y,此时的n ...

  7. 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 ...

  8. 贪心 Codeforces Round #297 (Div. 2) C. Ilya and Sticks

    题目传送门 /* 题意:给n个棍子,组成的矩形面积和最大,每根棍子可以-1 贪心:排序后,相邻的进行比较,若可以读入x[p++],然后两两相乘相加就可以了 */ #include <cstdio ...

  9. 贪心 Codeforces Round #304 (Div. 2) B. Soldier and Badges

    题目传送门 /* 题意:问最少增加多少值使变成递增序列 贪心:排序后,每一个值改为前一个值+1,有可能a[i-1] = a[i] + 1,所以要 >= */ #include <cstdi ...

  10. 贪心 Codeforces Round #303 (Div. 2) B. Equidistant String

    题目传送门 /* 题意:找到一个字符串p,使得它和s,t的不同的总个数相同 贪心:假设p与s相同,奇偶变换赋值,当是偶数,则有答案 */ #include <cstdio> #includ ...

随机推荐

  1. codeforces 9 div2 C.Hexadecimal's Numbers 暴力打表

    C. Hexadecimal's Numbers time limit per test 1 second memory limit per test 64 megabytes input stand ...

  2. XML_CPP_ZC_libXml2

    1.错误信息: /* * Use the following function to reset the two global variables * xmlGenericError and xmlG ...

  3. 读underscore

    最近在拜读只有1700行(含注释)代码的Underscore.js 1.9.1,记录一些东西 (参考https://underscorejs.org/underscore.js,https://git ...

  4. 使用H5 canvas画一个坦克

      具体步骤如下:   1. 首先做出绘图区,作为坦克的战场   <canvas id="floor" width="800px" height=&quo ...

  5. 第一个mpvue小程序开发总结

    前言 说起小程序,其实在去年我都还只试着照着官方文档写过demo的,不过现在这家公司小程序做得比较多,我来之后也参与了几个小程序的开发了,最开始那几个是用的wepy,最近一个开始转用mpvue开发,最 ...

  6. Python - Learn Note (2)

    Python注释 Python的注释以#开头,后面的文字直到行尾都算注释 Python基本数据类型 整数.浮点数(浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置 ...

  7. 如何在.Net的MySqlCommand里面使用MySql用户自定义变量?

    Mysql使用@符号代表变量,但C#也恰好使用@代表用户自定义变量,这样两者就会正好冲突了. SELECT () AS rowId, u.*, r.RoleName FROM userinfo u L ...

  8. js enter键激发事件

    document.onkeydown = function (e) {            if (!e) e = window.event;            if ((e.keyCode | ...

  9. Winform开发常用控件之ComboBox、ListBox

    ComboBox就是我们常见的下拉框,对于此类控件,我们最关心的当然是数据的绑定和选择值得获取. 首先介绍个属性DropDownStyle,如果不允许ComboBox输入值,只能选择,就选DropDo ...

  10. 使用peach工具进行fuzz测试

    本文简要介绍了Fuzz 工具Peach的使用,并通过文件格式 Fuzz举例阐述了 Peach Pit 文件的编写. 本文转自“绿盟科技博客”:http://blog.nsfocus.net/peach ...