[2021] 阿里巴巴 [编程题]知识竞赛

最近准备面试刷题,写到一题发现了非常巧妙的解法,在这里记录一下。

题目

在这里插入图片描述

思路

我们可以对员工的能力值 A A A和能力值 B B B的差的绝对值非递减排序,这样,排序在后面的员工就决定了较差的能力是 A A A还是 B B B

举个例子
假设我们选出了两名员工 i i i j j j,有 i < j i < j i<j
假设 A i < B i A_i < B_i Ai<Bi
那么员工 j j j就有两种情况, A j < = B j A_j <= B_j Aj<=Bj 或者 A j > B j A_j > B_j Aj>Bj

这里分开讨论
1、 A j < = B j A_j <= B_j Aj<=Bj,那毫无疑问,最终答案是 A i + A j 2 \frac{A_i+A_j}{2} 2Ai+Aj
2、 A j > B j A_j > B_j Aj>Bj,这种情况最终答案应该是 B i + B j 2 \frac{B_i+B_j}{2} 2Bi+Bj,因为 B i − A i < A j − B j B_i-A_i < A_j-B_j BiAi<AjBj B i + B j < A i + A j B_i+B_j < A_i+A_j Bi+Bj<Ai+Aj(我们已经对一个员工能力值的差值排序过了)

A i > B i A_i > B_i Ai>Bi,则和上面同理。

那么,我们可以知道,在排序之后的两个能力值之和的最小值由靠后的员工决定,所以可以顺序遍历排序后的员工,记录之前所有员工的两个能力值的最大值,取当前员工能力值较小的和该能力值的历史最大值相加后取平均即可。

#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
#pragma GCC optimize(3)
typedef long long ll;
#define INF 0x3f3f3f3f
const int mod = 1e9 + 7;
const int maxn = 1e5 + 5;
#define iss ios::sync_with_stdio(false)
#define debug(x) cout << #x << ": " << x << endl;
inline ll read()
{
    ll s = 0, w = 1;
    char ch = getchar();
    while (ch < 48 || ch > 57)
    {
        if (ch == '-')
            w = -1;
        ch = getchar();
    }
    while (ch >= 48 && ch <= 57)
        s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
    return s * w;
}
pair<int,int> par[200005];
int main(){
    int n = read();
    for(int i = 0 ; i < n ; ++i){
        par[i].first = read();
        par[i].second = read();
    }
    sort(par,par+n,
        [](pair<int,int> a,pair<int,int> b){
            return abs(a.first - a.second) < abs(b.first - b.second);
        }
    );//按能力值绝对值排序
    int ma = par[0].first,mb = par[0].second;//分别是能力值A和B的最大值
    int maxi = 0;
    for(int i = 1 ; i < n ; ++i){
        int res;//res表示取当前员工,和之前一个员工,最大的min(A,B)的大小
        if(par[i].first > par[i].second) res = par[i].second + mb;
        else res = par[i].first + ma;
        maxi = max(maxi,res);
        ma = max(ma,par[i].first);
        mb = max(mb,par[i].second);
    }
    printf("%.1f\n",maxi/2.0);
    
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值