ABC327现场

image.png

看到我的名字颜色了么?这就是我的实力,嗯对我是个菜逼/oh/oh/oh

EF做太慢了,前四题发挥稳定没吃罚时。

A

portal

题意:给定一个长度为 \(n\) 的字符串 \(s\),问他是否存在一对相邻的字母 'a' 和 'b'?\(1\leq n\leq 100\)

Solution

暴力枚举就行,十分的 low IQ。

\(\\\)

Code
// stODDDDDDDDDDDDDDDDDDDDDDDDDDD hzt CCCCCCCCCCCCCCCCCCCCCCCCCOrz

#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>

using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int kN = 100 + 1;

int n;
string s;

int main() {
  cin.tie(0)->sync_with_stdio(0);
  cin >> n >> s;
  bool t = 0;
  for (int i = 0; i < s.size() - 1; i++) {
    if (s[i] == 'a' && s[i + 1] == 'b' || s[i] == 'b' && s[i + 1] == 'a') {
      t = 1;
    }
  }
  if (t) {
    cout << "Yes\n";
  } else {
    cout << "No\n";
  }
  return 0;
}

B

portal

题意:给定一个整数 \(n\),问是否存在一个 \(k\) 使 \(k^k = n\)\(1\leq n\leq 10^{18}\)

Solution

发现 \(k\) 非常小,暴力枚举即可。

\(\\\)

Code
// stODDDDDDDDDDDDDDDDDDDDDDDDDDD hzt CCCCCCCCCCCCCCCCCCCCCCCCCOrz

#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>

using namespace std;
using LL = long long;
using PII = pair<int, int>;

LL n;

int main() {
  cin.tie(0)->sync_with_stdio(0);
  cin >> n;
  LL w = 1;
  for (int i = 1; i <= 100; i++) {
    w = 1;
    for (int j = 1; j <= i; j++) {
      w *= i;
    }
    if (w == n) {
      cout << i << '\n';
      return 0;
    } else if (w > n) {
      cout << "-1\n";
      return 0;
    }
  }
  return 0;
}

C

portal

题意:给定一个九宫格,问是否能使每行、每列、每宫格中 \(1~9\) 分别正好出现一次。

Solution

暴力枚举即可。ABC 特有的纯码量题。

\(\\\)

Code
// stODDDDDDDDDDDDDDDDDDDDDDDDDDD hzt CCCCCCCCCCCCCCCCCCCCCCCCCOrz

#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>

using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int kN = 9 + 1;

int a[kN][kN];
int t[kN];

int main() {
  cin.tie(0)->sync_with_stdio(0);
  for (int i = 1; i <= 9; i++) {
    for (int j = 1; j <= 9; j++) {
      cin >> a[i][j];
    }
  }
  bool f = 1;
  for (int i = 1; i <= 9 && f; i++) {
    fill_n(t + 1, 9, 0);
    for (int j = 1; j <= 9; j++) {
      t[a[i][j]] = 1;
    }
    for (int j = 1; j <= 9; j++) {
      f &= t[j];
    }
  }
  for (int i = 1; i <= 9 && f; i++) {
    fill_n(t + 1, 9, 0);
    for (int j = 1; j <= 9; j++) {
      t[a[j][i]] = 1;
    }
    for (int j = 1; j <= 9; j++) {
      f &= t[j];
    }
  }
  for (int i = 1; i <= 9 && f; i += 3) {
    for (int j = 1; j <= 9 && f; j += 3) {
      fill_n(t + 1, 9, 0);
      for (int k = i; k <= i + 2; k++) {
        for (int l = j; l <= j + 2; l++) {
          t[a[k][l]] = 1;
        }
      }
      for (int k = 1; k <= 9; k++) {
        f &= t[k];
      }
    }
  }
  if (f) {
    cout << "Yes\n";
  } else {
    cout << "No\n";
  }
  return 0;
}

D

portal

题意:给定两个长度为 \(m\) 的序列 \(a\)\(b\),序列中每个数大小不超过 \(n\),问是否存在一个长度为 \(n\) 的 01 序列 \(x\),使对于所有 \(1\leq i\leq m\),有 \(x_{a_i}\) != \(x_{b_i}\)\(1\leq n, m\leq 2\times 10^5\)

我的 blog 不知道为什么 Latex 渲染 \(\neq\) 会出锅,只能 != 看了。

Solution

题面说到 \(x\) 是个 01 序列实际上就已经明示了它是个二分图:\(x_{a_i}\) != \(x_{b_i}\) 相当于连边 \(a_i\ to\ b_i\) 染色,因为 \(x\) 的值只能是 0 或 1,所以这个题就变成了二分图的判定。这里我不想写染色法,就随便写了个并查集,结果写了个 "f[x] = F(x)",还调了一两分钟。

\(\\\)

Code
// stODDDDDDDDDDDDDDDDDDDDDDDDDDD hzt CCCCCCCCCCCCCCCCCCCCCCCCCOrz

#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>

using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int kN = 2e5 + 1;

int n, m;
int a[kN], b[kN];

int fa[2 * kN];
int R(int x) {
  if (fa[x] == x) {
    return x;
  }
  fa[x] = R(fa[x]);
  return fa[x];
}
void M(int x, int y) {
  x = R(x), y = R(y);
  if (x == y) {
    return;
  }
  fa[x] = y;
}

int main() {
  cin.tie(0)->sync_with_stdio(0);
  cin >> n >> m;
  for (int i = 1; i <= m; i++) {
    cin >> a[i];
  }
  for (int i = 1; i <= m; i++) {
    cin >> b[i];
  }
  iota(fa, fa + 2 * n + 1, 0);
  for (int i = 1; i <= m; i++) {
    M(a[i], b[i] + n);
    M(a[i] + n, b[i]);
  }
  for (int i = 1; i <= n; i++) {
    if (R(i) == R(i + n)) {
      cout << "No\n";
      return 0;
    }
  }
  cout << "Yes\n";
  return 0;
}

E

portal

题意:给定一个长度为 \(n\) 的序列 \(p\),你可以从中选出一个长度为 \(k\) 的子序列 \(q\)\(k\) 可以自选),一个子序列的权值 \(R\) 表示如下:

\[R=\frac{\sum\limits_{i=1}^k(0.9)^{k - i}q_i}{\sum\limits^k_{i=1}(0.9)^{k-i}} - \frac{1200}{\sqrt{k}} \]

求所有子序列中 \(R\) 的最大值。*子序列不可打乱顺序。\(1\leq n\leq 5000\)

Solution

你感觉这个 \((0.9)^{k-i}\) 很烦,因为 \(k\) 的不确定他的值也无法确定。然而可以直接倒着做。设 \(f_{i, j}\) 表示考虑了后 \(i\) 个数,选了 \(j\) 个数的答案最大值,根据定义转移就有 \(f_{i, j} = \max(f_{i + 1, j}, f_{i + 1, j - 1} + (0.9)^{j - 1} p_i)\)。时间复杂度 \(O(n^2)\),足以通过此题。

\(\\\)

Code
// stODDDDDDDDDDDDDDDDDDDDDDDDDDD hzt CCCCCCCCCCCCCCCCCCCCCCCCCOrz

#include <algorithm>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <numeric>
#include <vector>

using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int kN = 5e3 + 2;
constexpr double kI = 1e18;

int n;
int p[kN];
double f[kN][kN], p9[kN];

int main() {
  cin.tie(0)->sync_with_stdio(0);
  cin >> n, p9[0] = 1;
  for (int i = 1; i <= n; i++) {
    cin >> p[i];
    p9[i] = 0.9 * p9[i - 1];
  }
  fill(f[0], f[n + 1] + n + 2, -kI);
  f[n + 1][0] = 0;
  for (int i = n; i >= 1; i--) {
    f[i][0] = 0;
    for (int j = 1; j <= n; j++) {
      // f[i][j] = f[i + 1][j];
      f[i][j] = max(f[i + 1][j], f[i + 1][j - 1] + p9[j - 1] * p[i]);
    }
  }
  double ans = -kI, s = 0;
  for (int i = 1; i <= n; i++) {
    s += p9[i - 1];
    ans = max(ans, f[1][i] / s - 1200.0 / sqrt(i));
  }
  cout << fixed << setprecision(8) << ans << '\n';
  return 0;
}

F

portal

题意:给定两个长度为 \(n\) 的序列 \(x_i\)\(t_i\),表示第 \(i\) 个苹果将在 \(t_i\) 时落在 \(x_i\) 上。你可以选择一段长度为 \(w-1\) 的位置区间和一段长度为 \(d-1\) 的时间区间。问最多有多少个苹果在你选定的时间与位置区间内落下。\(1\leq n, d, w, t_i, x_i \leq 2\times 10^5\)

Solution

你把位置看作一维,时间看作另一维,这个问题就转化为了固定矩形长宽的矩形最多点覆盖问题板子。线段树维护一下即可。

\(\\\)

Code
// stODDDDDDDDDDDDDDDDDDDDDDDDDDD hzt CCCCCCCCCCCCCCCCCCCCCCCCCOrz

#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>

using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int kN = 2e5 + 5;

struct Tree {
  int w, t;
} t[4 * kN];
void PU(int x) { t[x].w = max(t[2 * x].w, t[2 * x + 1].w); }
void PD(int x) {
  if (!t[x].t) {
    return;
  }
  t[2 * x].t += t[x].t, t[2 * x].w += t[x].t;
  t[2 * x + 1].t += t[x].t, t[2 * x + 1].w += t[x].t;
  t[x].t = 0;
}
void U(int L, int R, int w, int x, int l, int r) {
  if (R < l || r < L) {
    return;
  } else if (L <= l && r <= R) {
    t[x].w += w, t[x].t += w;
    return;
  }
  int m = (l + r) / 2;
  PD(x);
  U(L, R, w, x * 2, l, m);
  U(L, R, w, x * 2 + 1, m + 1, r);
  PU(x);
}
struct Node {
  int x, y, f;
  bool operator<(const Node& a) const { return PII(x, f) < PII(a.x, a.f); }
} a[2 * kN];

int n, d, h;
int main() {
  cin.tie(0)->sync_with_stdio(0);
  cin >> n >> d >> h, d--, h--;
  int tot = 0, L = 1e9, R = 0;
  for (int i = 1, x, y; i <= n; i++) {
    cin >> x >> y;
    L = min(L, y), R = max(R, y);
    a[++tot] = {x, y, 1}, a[++tot] = {x + d + 1, y, -1};
  }
  sort(a + 1, a + tot + 1);
  int ans = 0;
  for (int i = 1; i <= tot; i++) {
    int l = max(L, a[i].y), r = min(R, a[i].y + h);
    U(l, r, a[i].f, 1, L, R);
    ans = max(ans, t[1].w);
  }
  cout << ans << '\n';
  return 0;
}

G 我是真的不会,这就是 ABC 革新后的难度跨度么?

posted @ 2023-11-04 23:20  Lightwhite  阅读(13)  评论(0编辑  收藏  举报