CFR-835-Div-4解题报告

比赛传送门

D. Challenging Valleys

题意:给你一个数组,判断它是否为“山谷形”。

tourist 的做法是假想在最左边和最右边插入一个极大值(结果不变)来统一情况,然后只需要判断下凹(比左右两边都低)的位置个数。如果为 1 则正确。

By tourist

#include <bits/stdc++.h>

using namespace std;

#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int tt;
  cin >> tt;
  while (tt--) {
    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
      cin >> a[i];
    }
    int cnt = 0;
    int beg = 0;
    while (beg < n) {
      int end = beg;
      while (end + 1 < n && a[end + 1] == a[end]) {
        end += 1;
      }
      if (beg == 0 || a[beg - 1] > a[beg]) {
        if (end == n - 1 || a[end + 1] > a[end]) {
          cnt += 1;
        }
      }
      beg = end + 1;
    }
    cout << (cnt == 1 ? "YES" : "NO") << '\n';
  }
  return 0;
}

E. Binary Inversions

题意:给你一个 01 串,你最多可以将一位取反(也可以不取),问逆序对数最多为多少。

考虑预处理前缀和和后缀和,这样就可以 O(1) 得到前后缀的 01 个数。先算出总的逆序对个数,然后对于每一位,考虑取反该位的贡献即可。可以通过前后缀 01 个数很简单地求得。

By tourist

#include <bits/stdc++.h>

using namespace std;

#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int tt;
  cin >> tt;
  while (tt--) {
    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
      cin >> a[i];
    }
    vector<int> p0(n + 1);
    for (int i = 0; i < n; i++) {
      p0[i + 1] = p0[i] + (a[i] == 0);
    }
    vector<int> p1(n + 1);
    for (int i = 0; i < n; i++) {
      p1[i + 1] = p1[i] + (a[i] == 1);
    }
    long long inv = 0;
    int k1 = 0;
    for (int i = 0; i < n; i++) {
      if (a[i] == 1) {
        k1 += 1;
      } else {
        inv += k1;
      }
    }
    long long ans = inv;
    for (int i = 0; i < n; i++) {
      auto cur = inv;
      if (a[i] == 0) {
        cur -= p1[i];
        cur += p0[n] - p0[i + 1];
      } else {
        cur += p1[i];
        cur -= p0[n] - p0[i + 1];
      }
      ans = max(ans, cur);
    }
    cout << ans << '\n';
  }
  return 0;
}

F. Quests

题意:有 n 中物品,每中物品有一个价值,每种有无穷多个,当你拿走一个物品后 k 秒不能拿这个物品。问 k 最多为多少才能在 d 秒内拿到 c 的价值。

从大到小排序,二分答案,check 时循环选即可。有一些细节,比如 k>n 时的处理等。

By tourist

#include <bits/stdc++.h>

using namespace std;

#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int tt;
  cin >> tt;
  while (tt--) {
    int n, d;
    long long c;
    cin >> n >> c >> d;
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
      cin >> a[i];
    }
    sort(a.rbegin(), a.rend());
    int low = -1, high = d + 1;
    while (low < high) {
      int mid = (low + high + 1) >> 1;
      long long sum = 0;
      for (int i = 0; i < d; i++) {
        int id = i % (mid + 1);
        if (id < n) {
          sum += a[id];
        }
      }
      if (sum >= c) {
        low = mid;
      } else {
        high = mid - 1;
      }
    }
    if (low == d + 1) {
      cout << "Infinity" << '\n';
    } else {
      if (low == -1) {
        cout << "Impossible" << '\n';
      } else {
        cout << low << '\n';
      }
    }
  }
  return 0;
}

G. SlavicG's Favorite Problem

题意:有一个无根树,你初始在 a,有一个变量 x 初始为 0,每经过一条边都会异或上该边的边权。你能到达点 b 当且仅当 x 到达 b 时恰好为 0。你可以在任意时刻传送到任意位置一次(除了点 b),问是否能到达点 b

可以进行两遍搜索,一遍从 a 开始但不能走 b,一遍从 b 开始。判断是否能存在两个点 i,j,使得 ia 的距离和 jb 的距离相等(此时可以 aijb。用 set 维护即可。

By tourist

#include <bits/stdc++.h>

using namespace std;

#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int tt;
  cin >> tt;
  while (tt--) {
    int n, a, b;
    cin >> n >> a >> b;
    --a; --b;
    vector<vector<pair<int, int>>> g(n);
    for (int i = 0; i < n - 1; i++) {
      int x, y, w;
      cin >> x >> y >> w;
      --x; --y;
      g[x].emplace_back(y, w);
      g[y].emplace_back(x, w);
    }
    vector<int> d(n, -1);
    vector<int> que(1, a);
    d[a] = 0;
    for (int it = 0; it < (int) que.size(); it++) {
      for (auto& p : g[que[it]]) {
        int u = p.first;
        if (d[u] == -1 && u != b) {
          que.push_back(u);
          d[u] = d[que[it]] ^ p.second;
        }
      }
    }
    set<int> all;
    for (int i = 0; i < n; i++) {
      if (d[i] != -1) {
        all.insert(d[i]);
      }
    }
    d.assign(n, -1);
    que.assign(1, b);
    d[b] = 0;
    for (int it = 0; it < (int) que.size(); it++) {
      for (auto& p : g[que[it]]) {
        int u = p.first;
        if (d[u] == -1) {
          que.push_back(u);
          d[u] = d[que[it]] ^ p.second;
        }
      }
    }
    bool ok = false;
    for (int i = 0; i < n; i++) {
      if (i != b) {
        if (all.find(d[i]) != all.end()) {
          ok = true;
          break;
        }
      }
    }
    cout << (ok ? "YES" : "NO") << '\n';
  }
  return 0;
}
posted @   曹轩鸣  阅读(30)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起