OneKuma

OneKuma's Blog

One Lonely Kuma.
github
bilibili
twitter

Codeforces Round 935 (Div. 3) Solution

Contest

A. Setting up Camp#

There are 3 types of people who need to stay in tents, with aa, bb, and cc individuals respectively. The first type, Xiaoboqi, only wants to stay alone, the second type, Xida, must stay with 2 other people, and the third type is indifferent. Each tent can accommodate a maximum of 3 people. What is the minimum number of tents needed?

Xiaoboqi stays alone, Xida forms teams internally as much as possible, and the third type fills in the gaps left by Xida, then take the ceiling of the result divided by 3.

B. Fireworks#

There are two types of fireworks that explode at times 0,a,2a,3a,0,a,2a,3a,\dots and 0,b,2b,3b,0,b,2b,3b,\dots, with each explosion lasting m+1m+1 time units, meaning they explode at [0,m],[a,a+m],[2a,2a+m],[3a,3a+m],[0,m],[a,a+m],[2a,2a+m],[3a,3a+m],\dots and [0,m],[b,b+m],[2b,2b+m],[3b,3b+m],[0,m],[b,b+m],[2b,2b+m],[3b,3b+m],\dots respectively. For all time points, find the maximum number of fireworks that explode simultaneously.

Clearly, we can just check how many are exploding at time mm; the answer is (1+ma)+(1+mb)(1 + \lfloor \frac{m}{a} \rfloor) + (1 + \lfloor \frac{m}{b}\rfloor) ​.

C. Left and Right Houses#

There is a street with nn households, divided into left and right sides by a road. Each household has a preference to live on the left or right side represented by a1,a2,,ana_1, a_2, \dots, a_n. Now, you need to arrange the position of the road such that at least half of the households on both sides are satisfied, while minimizing the distance from the midpoint and the road's coordinate.

Although there are many conditions, you only need to enumerate where to place the road from left to right, keeping track of the prefix sums to quickly check for validity.

D. Seraphim the Owl#

There is a queue of length nn, and you are currently standing at the far right of the queue (position n+1n+1). Assuming you are currently at position ii, you can jump left to position j<ij < i, costing aj+k=j+1ibka_j + \sum_{k=j+1}^{i} b_k. Your goal is to jump to a position less than or equal to mm with the minimum cost.

The original problem is equivalent to choosing a cost aia_i or bib_i for each position, as each position will only choose one to calculate once, and the last cost is aia_i, allowing for a valid jump plan. Note that you need to enumerate the last landing point within [1,m][1,m], as there may be cases where bb is very small and aa is very large.

You are given a shuffled permutation of length nn, and you can swap any two positions at most 2 times to ensure that binary search can find the answer for this permutation.

At first glance, it seems you need to construct a sequence of length log2n\lfloor \log_2n \rfloor to make binary search work correctly, but that's a misconception. It can be observed that although the binary search process is chaotic, it effectively narrows down the target interval to a unique one. We only need to let it run freely and place the answer in a randomly chosen target position.

During the binary search process, we mark which positions have been visited, allowing the remaining positions to be swapped freely, and finally find a position that hasn't been touched to swap. Note that during the random binary search, if the answer is found midway, an additional operation is needed to move the answer elsewhere.

That's roughly the idea; I just wrote it down randomly, added some assert, but it works.

F. Kirill and Mushrooms#

You are given nn mushrooms, each with a weight a1,a2,a3,,ana_1,a_2,a_3,\dots,a_n. You can select kk mushrooms, and the weight is the minimum weight of the selected mushrooms multiplied by kk. There is also a restriction: there is a permutation p1,p2,p3,,pnp_1, p_2, p_3, \dots, p_n, and if you choose the kk mushrooms, the weights of mushrooms ap1,ap2,,apk1a_{p_1}, a_{p_2}, \dots, a_{p_{k-1}} are cleared and cannot be chosen. Find the minimum number of selections under the maximum weight condition.

Enumerate how many mushrooms are selected from 11 to nn (though it can only be roughly half), maintaining the top kk remaining mushrooms and clearing the corresponding mushrooms.

It seems like you could directly use a heap, but I didn't want to think too much and just used a binary indexed tree to maintain the kk​ largest.

G. Cook and Porridge#

There are nn people lined up for a meal, and there are a set of rules for sorting them in the queue. Determine if everyone can eat once within the first DD time units, or report that it's not possible.

I haven't written it; it seems like I need to maintain some data structure to handle it, but I don't want to write all the details.

H. GCD is Greater#

You are given an array of size nn, and you need to divide it into two parts, with each part containing at least 2 elements. The first part requires calculating their gcd\gcd, while the second part requires calculating their bitwiseAND\operatorname{bitwise AND} plus a parameter xx. Determine if there exists a partition scheme such that the weight of the first part is strictly greater than that of the second part.

Clearly, the gcd\gcd of the first part only needs 2 numbers because the more numbers there are, the smaller the gcd\gcd becomes; similarly, the bitwiseAND\operatorname{bitwise AND} also becomes smaller with more numbers, but it meets the target.

So I can directly enumerate the gcd\gcd and then figure out how to judge it, but I haven't written it down or thought it through; it should be doable.

Code#

A. Setting up Camp#

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <utility>
#include <set>
#include <map>
#include <vector>

using namespace std;

const int inf = 1e9 + 7;
const int maxn = 300000 + 5;

int n, a[maxn];

int main() {
#ifdef DEBUG
  freopen("../assets/in.txt", "r", stdin);
#endif

  int T;
  scanf("%d", &T);
  while (T--) {
    int a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    int cnt = a;
    cnt += b / 3;
    b %= 3;
    if (b > 0 && b + c < 3) {
      puts("-1");
      continue;
    } else {
      if (b > 0) {
        c -= 3 - b;
        cnt++;
      }
      cnt += (c + 2) / 3;
      printf("%d\n", cnt);
    }
  }

  return 0;
}

B. Fireworks#

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <utility>
#include <set>
#include <map>
#include <vector>

using namespace std;

const int inf = 1e9 + 7;
const int maxn = 300000 + 5;

int main() {
#ifdef DEBUG
  freopen("../assets/in.txt", "r", stdin);
#endif

  int T;
  scanf("%d", &T);
  while (T--) {
    long long a, b, m;
    scanf("%lld%lld%lld", &a, &b, &m);
    long long ans = 2 + m / a + m / b;
    printf("%lld\n", ans);
  }

  return 0;
}

C. Left and Right Houses#

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cassert>
#include <algorithm>
#include <utility>
#include <set>
#include <map>
#include <vector>

using namespace std;

const int inf = 1e9 + 7;
const int maxn = 300000 + 5;

int n, pre[maxn], suf[maxn];
char buf[maxn];

int main() {
#ifdef DEBUG
  freopen("../assets/in.txt", "r", stdin);
#endif

  int T;
  scanf("%d", &T);
  while (T--) {
    scanf("%d%s", &n, buf + 1);
    pre[0] = 0; suf[n + 1] = 0;
    for (int i = 1; i <= n; i++) {
      pre[i] = pre[i - 1] + (buf[i] == '0');
    }
    for (int i = n; i >= 1; i--) {
      suf[i] = suf[i + 1] + (buf[i] == '1');
    }
    pre[n + 1] = pre[n]; suf[0] = suf[1];

    auto check = [&](int p) {
      int l = pre[p];
      int r = suf[p + 1];
      return l >= (p + 1) / 2 && r >= (n - p + 1) / 2;
    };
    int ans = -1;
    for (int i = 0; i <= n; i++) {
      if (check(i)) {
        if (ans == -1 || abs(n - ans - ans) > abs(n - i - i)) {
          ans = i;
        }
      }
    }
    assert(ans != -1);
    printf("%d\n", ans);
  }

  return 0;
}

D. Seraphim the Owl#

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <utility>
#include <set>
#include <map>
#include <vector>

using namespace std;

const int inf = 1e9 + 7;
const int maxn = 300000 + 5;

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

int main() {
#ifdef DEBUG
  freopen("../assets/in.txt", "r", stdin);
#endif

  int T;
  scanf("%d", &T);
  while (T--) {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) {
      scanf("%d", a + i);
    }
    for (int i = 1; i <= n; i++) {
      scanf("%d", b + i);
    }

    long long ans = 0, mn = a[m], sum = 0;
    for (int i = n; i > m; i--) {
      ans += min(a[i], b[i]);
    }
    for (int i = m; i >= 1; i--) {
      mn = min(mn, a[i] + sum);
      sum += b[i];
    }
    printf("%lld\n", ans + mn);
  }

  return 0;
}

E. Binary Search#

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cassert>
#include <algorithm>
#include <utility>
#include <set>
#include <map>
#include <vector>

using namespace std;

const int inf = 1e9 + 7;
const int maxn = 300000 + 5;

int n, x, a[maxn];

void check() {
//  for (int i = 1; i <= n; i++) {
//    printf("%d%c", a[i], " \n"[i == n]);
//  }

  int l = 1, r = n + 1;
  while (r - l > 1) {
    int m = (l + r) / 2;

    if (a[m] <= x) {
      l = m;
    } else {
      r = m;
    }
  }
//  printf(": %d %d\n", l, a[l]);

  assert(r - l == 1 && a[l] == x);
}

int main() {
#ifdef DEBUG
  freopen("../assets/in.txt", "r", stdin);
#endif

  int T;
  scanf("%d", &T);
  while (T--) {
    scanf("%d%d", &n, &x);
    for (int i = 1; i <= n; i++) {
      scanf("%d", a + i);
    }

    vector<pair<int,int>> ans;

    int l = 1, r = n + 1;
    vector<int> visited(n + 1, 0);
    while (r - l > 1) {
      int m = (l + r) / 2;

      if (a[m] == x && r - l > 1) {
        int found = -1;
        for (int i = 1; found == -1 && i <= n; i++) {
          if (!visited[i]) found = i;
        }
        assert(found != -1);
        ans.push_back({ m, found });
        swap(a[m], a[found]);
      }

      visited[m] = 1;

      if (a[m] <= x) {
        l = m;
      } else {
        r = m;
      }
    }

    if (a[l] != x) {
      int found = -1;
      for (int i = 1; found == -1 && i <= n; i++) {
        if (a[i] == x) found = i;
      }
      assert(found != -1 && !visited[found]);
      visited[found] = 1;

      ans.push_back({ found, l });
      swap(a[found], a[l]);
    }

    printf("%d\n", (int) ans.size());
    for (auto& p: ans) {
      printf("%d %d\n", p.first, p.second);
    }

    check();
  }

  return 0;
}

F. Kirill and Mushrooms#

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <utility>
#include <set>
#include <map>
#include <vector>

using namespace std;

const int inf = 1e9 + 7;
const int maxn = 300000 + 5;

struct BIT {
  static const int R = 1 << 21;

  int a[R];

  inline int lowbit(int x) { return x & -x; }

  void insert(int i, int v) {
    for (; i < R; i += lowbit(i)) a[i] += v;
  }
  void clear(int i) {
    for (; i < R; i += lowbit(i)) a[i] = 0;
  }

  int findx(int p, int rk) {
    // if (p > R) return -1;
    if (p & 1) {
      // if (p + (a[p] < rk) > R) return -1;
      return p + (a[p] < rk);
    } else {
      if (rk > a[p]) return findx(p + lowbit(p) / 2, rk - a[p]);
      else return findx(p - lowbit(p) / 2, rk);
    }
  }
  int findx(int rk) {
    return findx(R >> 1, rk);
  }
} f;

int n, a[maxn], p[maxn];

int main() {
#ifdef DEBUG
  freopen("../assets/in.txt", "r", stdin);
#endif

  int T;
  scanf("%d", &T);
  while (T--) {
    scanf("%d", &n);

    vector<int> lsh;
    auto gid = [&](int x) -> int {
      return int(lsh.end() - lower_bound(lsh.begin(), lsh.end(), x));
    };

    for (int i = 1; i <= n; i++) {
      scanf("%d", a + i);
      lsh.push_back(a[i]);
    }
    for (int i = 1; i <= n; i++) {
      scanf("%d", p + i);
    }

    sort(lsh.begin(), lsh.end());
    lsh.resize(unique(lsh.begin(), lsh.end()) - lsh.begin());
    for (int i = 1; i <= n; i++) {
      f.insert(gid(a[i]), 1);
    }

    long long ans = 0;
    int cnt = 0;
    for (int i = 1; i + i - 1 <= n; i++) {
      int id = f.findx(i);
      int val = lsh[lsh.size() - id];
//      printf("Find: %d %d\n", id, val);
      if (1ll * val * i > ans) {
        ans = 1ll * val * i;
        cnt = i;
      }

      // Delete
      f.insert(gid(a[p[i]]), -1);
    }

    printf("%lld %d\n", ans, cnt);

    for (int i = 1; i <= n; i++) f.clear(gid(a[i]));
  }

  return 0;
}
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.