Codeforces Round661 Div3 [CF1399] 题解

由 5+1 发布

比赛链接

A Remove Smallest

$$\color{orange}普及-\color{black}模拟$$

题目让我们算这个数组是不是连续的(允许相等)数,如果是输出 YES 否则输出 NO

为了方便之后删减元素,我使用 vector 容器。

因为给的数组不是有序的,所以需要先排序,排序用 sort 就行了。

之后我们就可以从小到大俩俩比较( $w_i$ 和 $w_{i-1}$ ),如果 $w_i+w_{i-1}$ 超过 $1$ ,那么就直接给一个 NO 就行了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;

inline int absd (int x)
{
  return x > 0 ? x : -x;
}

vector <int> a;

int main ()
{
  int t, n;
  scanf ("%d", &t);
  while (t --)
  {
    a.clear();
    scanf ("%d", &n);
    for (int i = 1; i <= n; i ++)
    {
      int x;
      scanf ("%d", &x);
      a.push_back(x);
    }
    int f = 0;
    sort (a.begin(), a.end());
    for (int i = 1; i < a.size(); i ++)
    {
      if (a[i] - a[i - 1] > 1)
      {
        f = 1;
        break;
      }
    }
    printf (f ? "NO\n" : "YES\n");
  }
  return 0;
}

int absd (int x); 是手动处理绝对值的函数。

B Gifts Fixing

$$\color{orange}普及-\color{black}暴力枚举$$

注 数据范围能告诉你算法 $1 \le n \le 50$

题目就是让我们去算至少需要几步能将所有的数降到最小值。

题目说一共有 $3$ 种操作:

  1. $a_i \gets a_i-1$
  2. $b_i \gets b_i-1$
  3. $a_i \gets a_i-1;b_i \gets b_i-1$

其实就是当前 $a_i$ 与 $b_i$ 那个减那个,如果一样多就都减。

我们声明一个类 Gifts 里面有 a,b 两个成员。

struct Gifts
{
  int a, b;
};

Gifts v[] 来存输入的数据,用 Gifts vmin 来存储最小值。

之后暴力循环 v 中的每一个元素,用 ab 记录当前值减去最小值(即当前需要减少几次),ab 的 $max$ 即为这次需要挪动的次数。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <climits>
using namespace std;
typedef long long ll;

struct Gifts
{
  int a, b;
};

int main ()
{
  int t, n;
  scanf ("%d", &t);
  while (t --)
  {
    scanf ("%d", &n);
    Gifts v[55];
    Gifts vmin;
    vmin.a = vmin.b = INT_MAX;
    for (int i = 1; i <= n; i ++)
    {
      scanf ("%d", &v[i].a);
      vmin.a = min (vmin.a, v[i].a);
    }
    for (int i = 1; i <= n; i ++)
    {
      scanf ("%d", &v[i].b);
      vmin.b = min (vmin.b, v[i].b);
    }
    ll ans = 0;
    for (int i = 1; i <= n; i ++)
    {
      int a = v[i].a - vmin.a,
          b = v[i].b - vmin.b;
      ans = ans + max (a, b);
    }
    printf ("%lld\n", ans);
  }
  return 0;
}

C Boats Competition

$$\color{orange}普及/提高-\color{black}暴力枚举/二分答案$$

题目给我们一个数组 $w$ ,让我们在这个数组中求出在这 $n$ 个数的数列 $w$ 中两两相加,一共有多少组相等的。

我们枚举所有组的重量和 $i$ ( $i=w_x+w_y;2 \le i \le n \times 2$ ),在里面进行$二分答案$,二分这些重量里面那些可能组队(下标)。

  • 如果左面的重量加上右面的重量大于总重量( $w_l+w_r>i$ ),那么就扔掉右面的那个
  • 如果反过来( $w_l+w_r<i$ ),那么就扔掉左面的那个
  • 如果正好( $w_l+w_r=i$ ),那么就记录一个ans并扔掉左面的和右面的

为了保证上面的成立,必须先排序。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <algorithm>
using namespace std;


int n, w[55], c[55];

int main ()
{
  int t;
  scanf ("%d", &t);
  while (t --)
  {
    scanf ("%d", &n);
    for (int i = 1; i <= n; i ++)
    {
      scanf ("%d", &w[i]);
    }
    sort (w + 1, w + n + 1);
    int ans = 0;
    for (int i = 2; i <= n * 2; i ++)
    {
      int l = 1, r = n, tans = 0;
      while (l < r)
      {
        if (w[l] + w[r] > i)
        {
          r --;
        }
        else if (w[l] + w[r] < i)
        {
          l ++;
        }
        else
        {
          tans ++;
          r --, l ++;
        }
      }
      ans = max (ans, tans);
    }
    printf ("%d\n", ans);
  }
  return 0;
}

注 等级划分引自洛谷


暂无评论

发表评论