题解 CF934A 【A Compatible Pair】 ——贪心
题意:
给定两个数列 \(A\) 、 \(B\) ,元素个数分别为 \(n\) , \(m\) \((2 \le n,m \le 50)\) 。数列中所有元素大小均在 \(-10^{9}\) 到 \(10^{9}\) 之间。
现要求在 \(A\) 数列中删掉一个元素,使得 \(A\) 中任一元素和 \(B\) 中任一元素相乘的共 \((n-1) \times m\) 种可能的值中的最大值最小。输出该最大值。
题解:
其实这题的 \(n, m\) 都可以开大到 \(10^6\)。
我的做法是 \(O(n+m)\) 的贪心。
先考虑不拿走元素的情况。那么对答案有贡献的元素只有可能是 \(A,B\) 中最大的元素和最小的元素。可以证明。
假设在 \(B\) 中挑了一个元素的值为 \(k\),那么最终得出的这个值 \(y\) 与在 \(A\) 中挑出的元素 \(x\) 成正比例关系:\(y = kx\)。
这时候可以分类:
当 \(k>0\) 时,\(y\) 随 \(x\) 的增大而增大。所以当 \(x\) 取最大值时,\(y\) 才会是最大值。
当 \(k=0\) 时,无论 \(x\) 取何值,\(y\) 的值都为 \(0\)。此时我们可以当做取了最大值或最小值。
当 \(k<0\) 时,\(y\) 随 \(x\) 的增大而减小。所以当 \(x\) 取最小值时,\(y\) 才会是最大值。
终上所述,当 \(x\) 取最大值或最小值时,\(y\) 存在最大值。
所以我们应该挑 \(A\) 中最大或最小的元素。\(B\) 同理。
那么 \(y\) 的最大值为 \(\max(Max_A \cdot Max_B, Max_A \cdot Min_B, Min_A \cdot Max_B, Min_A \cdot Min_B)\)。
有 \(Max_A \cdot Max_B\) 和 \(Min_A \cdot Min_B\) 很好想到,那么为什么还要 \(Max_A \cdot Min_B\) 和 \(Min_A \cdot Max_B\) 呢?
有一组数据:
3 3
-3 -2 -1
1 2 3
显然答案一定是负数,为了使答案最大,这个值的绝对值应该越小。这样,就出现了 \(Max_A \cdot Min_B\) 了。
再考虑删除的情况。为了删除后的最大值最小,肯定拿走的数要对答案有贡献,那么就一定是 \(Max_A\) 或者 \(Min_A\)。此时 \(Maxer_A\) 和 \(Miner_A\) 就分别成为了 \(A\) 的最大值和 \(A\) 的最小值。再分别拿走 \(Max_A\)、\(Min_A\),并分别用 \(Maxer_A\)、\(Miner_A\) 代替,代入上方公式,取较小值,就是最后答案了。
最大值、次大值、最小值、次小值在输入时就可以求出,不需要再花费 \(n log n\) 的排序,也可以节省空间。
时间复杂度仅有 \(O(n+m)\)。
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long llt;
const llt INF = 0x7F7F7F7F7F7F7F7F;
int n, m;
llt Max1 = -INF, Maxer1 = -INF, Min1 = INF, Miner1 = INF, Max2 = -INF, Min2 = INF;
void init() {
scanf("%d %d", &n, &m);
}
void solve() {
for (int i = 1; i <= n; ++i) {
llt x;
scanf("%lld", &x);
if (x > Max1) {
Maxer1 = Max1;
Max1 = x;
} else if (x > Maxer1)
Maxer1 = x;
if (x < Min1) {
Miner1 = Min1;
Min1 = x;
} else if (x < Miner1)
Miner1 = x;
}
for (int i = 1; i <= m; ++i) {
llt x;
scanf("%lld", &x);
Min2 = min(Min2, x);
Max2 = max(Max2, x);
}
//拿走值最大的元素
llt ans1 = max( max(Maxer1 * Max2, Maxer1 * Min2), max(Min1 * Max2, Min1 * Min2) );
//拿走值最小的元素
llt ans2 = max( max(Max1 * Max2, Max1 * Min2), max(Miner1 * Max2, Miner1 * Min2) );
llt ans = min(ans1, ans2);
printf("%lld\n", ans);
}
int main() {
init();
solve();
return 0;
}
题解 CF934A 【A Compatible Pair】 ——贪心的更多相关文章
- CF934A A Compatible Pair
A Compatible Pair time limit per test 1 second memory limit per test 256 megabytes input standard in ...
- CF934A A Compatible Pair 题解
Content 有两个数列 \(A\) 和 \(B\),\(A\) 数列里面有 \(n\) 个元素,\(B\) 数列里面有 \(m\) 个元素,现在请从 \(A\) 数列中删除一个数,使得 \(A\) ...
- 【题解】P1712 [NOI2016]区间(贪心+线段树)
[题解]P1712 [NOI2016]区间(贪心+线段树) 一个observe是,对于一个合法的方案,将其线段长度按照从大到小排序后,他极差的来源是第一个和最后一个.或者说,读入的线段按照长度分类后, ...
- Codeforces 934.A A Compatible Pair
A. A Compatible Pair time limit per test 1 second memory limit per test 256 megabytes input standard ...
- Codeforces Round #462 (Div. 2) A Compatible Pair
A. A Compatible Pair time limit per test1 second memory limit per test256 megabytes Problem Descript ...
- 【题解】Cut the Sequence(贪心区间覆盖)
[题解]Cut the Sequence(贪心区间覆盖) POJ - 3017 题意: 给定一大堆线段,问用这些线段覆盖一个连续区间1-x的最小使用线段的数量. 题解 考虑一个这样的贪心: 先按照左端 ...
- Codeforces 934 A.Compatible Pair
http://codeforces.com/contest/934 A. A Compatible Pair time limit per test 1 second memory limit p ...
- 【题解】[HNOI2015]菜肴制作(贪心+topo序)
[题解][HNOI2015]菜肴制作(贪心+topo序) 题意:请你构造一个排列\(p[i]\)使得对于数组\(arc[i]=p[i]\)的字典序最小,并且对于给定的有序数对\((u,v)\)保证你给 ...
- 【题解】P4755 Beautiful Pair(启发式合并的思路+分治=启发式分治)
[题解]P4755 Beautiful Pair upd: 之前一个first second烦了,现在AC了 由于之前是直接抄std写的,所以没有什么心得体会,今天自己写写发现 不知道为啥\(90\) ...
随机推荐
- vi命令设置行号
1. :set nu :显示行号
- ES6新特性-函数的简写(箭头函数)
通常函数的定义方法 var fn = function(...){ ...... } //例如: var add = function(a,b){ return a+b; } //或者: functi ...
- hightopo学习之旅一 -- 节点动画
参照官网 动画手册 1.引入所需HT文件 <script src="plugins/ht/core/ht.js"></script> <script ...
- 多个if、elif和else的搭配使用
if-if-if-搭配成的语句块,会一个个去匹配是否满足if里面的语句; if与elif的搭配成的语句块,当匹配到if或者elif语句判断为True的时候,那么不会执行下面elif以及else里面的语 ...
- dubbo搭建
1.安装java : yum install java 2.下载Tomcat: wget http://mirrors.shu.edu.cn/apache/tomcat/tomcat-9/v9.0.1 ...
- CSS之CSS的三种基本的定位机制(普通流,定位,浮动)
一.普通流 普通流中元素框的位置由元素在XHTML中的位置决定.块级元素从上到下依次排列,框之间的垂直距离由框的垂直margin计算得到.行内元素在一行中水平布置. 普通流就是html文档中的元素如块 ...
- 将 notepad++ 添加到鼠标右键菜单 带图标
1.打开注册表编辑器,HKEY_CLASSES_ROOT\*\shell目录点击右键.新建-->项,这里命名的项则就是鼠标右键列表里面显示的内容,这里起名为[Edit With Notepad+ ...
- 让windows10的右键菜单既显示传统cmd又显示powershell
在windows10的资源管理器中,按住shift点击右键,只显示 open powershell window here,却没有传统的cmd 解决方法就是修改注册表: HKEY_LOCAL_MACH ...
- EXCEL对比在职员工与离职员工
EXCEL 在B1中 填写这个 =VLOOKUP(A1,C:C,1,0) 然后往下拉 只要有出现#N/A 说明已经离职了 公司需要
- mysql服务启动不了 More help is available by typing NET HELPMSG 3534
解决方法:参考 注意:如果安装MySQL的时候改了端口(如从3306改成3307),则my.ini配置文件的端口也需要相应的修改