「题解」Codeforces Round 891 (Div. 3)

A. Array Coloring

Problem

题目

Sol & Code

只有数列的和为偶数时才符合要求,即有任意个偶数,偶数个奇数。

将这些数分成两部分,发现两部分初始值 \(0\) 为偶数,偶数不会影响奇偶性,故需要偶数个奇数。

#include <bits/stdc++.h>
#define N 51

typedef long long ll;

int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }

int T, n, a[N];

int main() {
  scanf("%d", &T);
  while (T--) {
    scanf("%d", &n);
    int sum = 0;
    for (int i = 1 ; i <= n; ++i) {
      scanf("%d", &a[i]);
      sum += a[i];
    }
    if (sum & 1) puts("NO");
    else puts("YES");
  }
  return 0;
}

B. Maximum Rounding

Problem

题目

Sol & Code

贪心,尽量进位即可

#include <bits/stdc++.h>

typedef long long ll;

int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }

int T;
std::string s;

int main() {
  scanf("%d", &T);
  while (T--) {
    std::cin >> s;
    int n = s.length();
    int res = 0, pos = n;
    for (int i = n - 1; i >= 0; --i) {
      if (s[i] + res - '0' >= 5) res = 1, pos = i;
      else res = 0;
    }
    if (pos == n) std::cout << s << '\n';
    else {
      for (int i = 0; i < pos - 1; ++i) putchar(s[i]);
      if (pos == 0) putchar('1');
      else putchar(s[pos - 1] + 1);
      for (int i = pos; i < n; ++i) putchar('0');
      puts("");
    }
  }
  return 0;
}

C. Assembly via Minimums

Problem

题目

Sol & Code

最小的数出现 \(n-1\) 次,次小的数出现 \(n-2\) 次,依次递推,最大的数取最大值即可,可知答案。

#include <bits/stdc++.h>
#define N 1000001

typedef long long ll;

int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }

int T, n, a[N];

int main() {
  scanf("%d", &T);
  while (T--) {
    scanf("%d", &n);
    int s = n * (n - 1) / 2;
    for (int i = 1; i <= s; ++i) scanf("%d", &a[i]);
    std::sort(a + 1, a + s + 1);
    int now = 1, ad = n - 1;
    while (now <= s) {
      printf("%d ", a[now]);
      now += ad;
      --ad;
    }
    printf("%d\n", a[s]);
  }
  return 0;
}

D. Strong Vertices

Problem

题目

Sol & Code

讨论两种情况 \(u\)\(v\) 有直接相连的路径有 \(a_u-a_v \geq b_u-b_v\),移相后 \(a_u - b_u \geq a_v - b_v\)

如果 \(u\)\(w\)\(w\)\(v\) 则有 \(a_u-a_v \geq b_w-b_w,a_w-a_w \geq b_v-b_v\) 相加得 \(a_u-a_v \geq b_u-b_v\),即只要 \(u\) 能到 \(v\) 则有 \(a_u - b_u \geq a_v - b_v\)

所以答案就是 \(a_u-a_v\) 的值为最大值的那几个。

我 nt 地用了 st。

#include <bits/stdc++.h>
#define N 200001

typedef long long ll;

int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }

int T, n, a[N], b[N], lg[N], ans[N], f[N][21];

int st(int l, int r) {
  if (l > r) return -2147483647;
  int len = r - l + 1;
  return max(f[l][lg[len] - 1], f[r - (1 << (lg[len] - 1)) + 1][lg[len] - 1]);
}

int main() {
  scanf("%d", &T);
  for (int i = 1; i < N; ++i) {
    lg[i] = lg[i - 1] + ((1 << lg[i - 1]) == i);
  }
  while (T--) {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
    for (int i = 1; i <= n; ++i) scanf("%d", &b[i]);
    for (int i = 1; i <= n; ++i) f[i][0] = a[i] - b[i];
    for (int j = 1; (1 << j) <= n; ++j) {
      for (int i = 1; i + (1 << j) - 1 <= n; ++i) {
        f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
      }
    }
    int cnt = 0;
    for (int i = 1; i <= n; ++i) {
      if (f[i][0] >= max(st(1, i - 1), st(i + 1, n))) ans[++cnt] = i;
    }
    printf("%d\n", cnt);
    for (int i = 1; i <= cnt; ++i) printf("%d ", ans[i]);
    puts("");
  }
  return 0;
}

E. Power of Points

Problem

题目

Sol & Code

可以发现答案是从这点到所有点的连线的长度和,每次统计答案 \(O(n)\),更新同理。

发现排序后更新只与前后点的数量有关,只需要 \(O(1)\) 更新。

#include <bits/stdc++.h>
#define N 200001

typedef long long ll;

int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }

int T, n;
ll ans[N];
struct point {
  int x, id;
  friend bool operator < (point p1, point p2) {
    return p1.x < p2.x;
  }
}p[N];

int main() {
  scanf("%d", &T);
  while (T--) {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
      scanf("%d", &p[i].x);
      p[i].id = i;
    }
    std::sort(p + 1, p + n + 1);
    ans[p[1].id] = 0;
    for (int i = 1; i <= n; ++i) ans[p[1].id] += std::abs(p[1].x - p[i].x) + 1;
    for (int i = 2; i <= n; ++i) {
      if (p[i].x != p[i - 1].x) {
        ans[p[i].id] = ans[p[i - 1].id] + 1ll * (p[i].x - p[i - 1].x) * (i - 1) - 1ll * (p[i].x - p[i - 1].x) * (n - i + 1);
      } else ans[p[i].id] = ans[p[i - 1].id];
    }
    for (int i = 1; i <= n; ++i) printf("%lld ", ans[i]);
    puts("");
  }
  return 0;
}

posted @ 2023-10-05 19:08  yu__xuan  阅读(12)  评论(0编辑  收藏  举报