AtcoderABC313场

A - To Be SaikyoA - To Be Saikyo

AtcoderABC313场_第1张图片AtcoderABC313场_第2张图片

题目大意

有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 
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?

AtcoderABC313场_第3张图片AtcoderABC313场_第4张图片AtcoderABC313场_第5张图片AtcoderABC313场_第6张图片

题目大意

给定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 
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

AtcoderABC313场_第7张图片AtcoderABC313场_第8张图片

题目大意

给定一个整数序列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
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;  
}

你可能感兴趣的:(算法)