AtcoderABC313场

A - To Be SaikyoA - To Be Saikyo

在这里插入图片描述在这里插入图片描述

题目大意

有N个人,编号从1到N。每个人有一个整数分数,称为编程能力;第i个人的编程能力是Pi分。人1需要多少分才能成为最强者?换句话说,最小非负整数x是多少,使得对于所有i ≠ 1,满足P1 + x > Pi?

思路分析

为了使第1个人成为最强者,他需要比其他人的分数都高。找出所有其他人的分数中的最大值max。因此,答案是max + 1 - P1。如果max已经小于等于P1,则答案是0,因为第1个人已经是最强者。

时间复杂度

O(N)

AC代码

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n; 
    vector<int> p(n);
    for (int i = 0; i < n; i++) {
        cin >> p[i]; 
    }
    int m = 0;
    for (int i = 1; i < n; i++) {
        m = max(m, p[i]); // 找到除了第一个人之外的最高分数
    }

    cout << max(0, m + 1 - p[0]) << endl;
    return 0;
}

B - Who is Saikyo?B - Who is Saikyo?

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

题目大意

给定N个竞技选手,他们之间存在优劣关系。优劣关系具有传递性,即若选手A优于选手B,选手B优于选手C,则选手A优于选手C。定义最强选手为对其他所有选手具有优势的选手。给定M个关系信息,判断是否能确定最强选手,并输出其编号。如果有多个可能为最强选手,输出-1。

思路分析

右边为被超过,最强不可能出现右边,记录右边程序员出现的次数de[i]。
如果某个程序员的计数值de[i]为0,说明他没有被其他程序员所超过,他就可能是最强程序员。如果存在多个计数值为0的程序员(在它之前的ans!=-1),程序会输出-1并终止程序。否则,程序会将最强程序员的索引加1赋值给变量ans,并输出ans的值。

时间复杂度

O(N+M)

AC代码

#include <bits/stdc++.h>
using namespace std;
int main() {
  int n, m;
  cin >> n >> m; 
  vector<int> deg(n);  
  
  while (m--) {
    int a, b;
    cin >> a >> b;  /
    --a, --b;  
    deg[b]++;  
  }
  int ans = -1;  
  for (int i = 0; i < n; i++) {
    if (deg[i] == 0) {  
      if (ans != -1) {  // 如果已经有选手被赋值给ans
        cout << -1 << endl;  // 输出-1,表示无法确定最强选手
        return 0;
      } else {
        ans = i + 1;  
      }
    }
  }
  
  cout << ans << endl;  
  return 0;
}

C - Approximate Equalization 2C - Approximate Equalization 2

在这里插入图片描述在这里插入图片描述

题目大意

给定一个整数序列A,可以进行以下操作任意次数(包括零次):
选择两个整数i和j(1≤i,j≤N),将A_i减一并将A_j加一。找到使得序列A的最大值和最小值之间的差最多为1所需的最小操作次数。

思路分析

将最大值逐渐减小,将最小值逐渐增大,来使得最大值和最小值之间的差最多为1。

  • 首先将序列A排序,这样最大值和最小值就会排列在序列a的末尾和开头。
  • 然后构造一个均匀分布的序列b,使得序列b的平均值接近每个元素之和的平均值。
  • 将多余的1分配给序列b的末尾的元素,以最大程度地减小操作次数。
  • 最后,计算序列a和序列b的元素之间的差值,得到最小操作次数。

时间复杂度

O(NlogN)

AC代码

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
    int n;
    cin >> n; 
    vector<int> a(n);  
    ll sum = 0; 

    for (int i = 0; i < n; i++) {
        cin >> a[i]; 
        sum += a[i]; 
    }

    sort(a.begin(), a.end());  
    vector<int> b(n, sum / n);  // 创建长度为N的数组b,初始值为sum/n
    for (int i = 0; i < sum % n; i++) {
        b[n - 1 - i]++;  // 将sum % n个1分别分配给数组b的尾部元素
    }

    ll ans = 0; 
    for (int i = 0; i < n; i++) {
        ans += abs(a[i] - b[i]); 
    }

    cout << ans / 2 << endl;  
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值