文章目录

Codeforces Global Round 23

发布于

比赛链接

题解

A

显然,如果数组不是全 $0$,就一定可以变成 $\left[1\right]$。

B

考虑最优情况一定是 $000...0 111...1$,所以要把数组里的 $1$ 都调到最后面。具体实现方法是遍历数组,一共有 $cnt$ 个 $1$,接着遍历数组的最后 $cnt$ 个元素,一共有 $k$ 个 $0$,则需要 $k$ 次操作。

C

如果 $a_i > a_{i + 1}$,则需要 $a_i - a_{i + 1}$ 后缀加 $i$ 使得 $a_{i + 1} = a_i$,所以我们使用一个 vector 来记录所有的可用操作,每次在 vectorlower_bound 一个大于等于 $a_i - a_{i + 1}$ 的操作来用,然后从 vector 里删除。这样是 $\mathcal O\left(n \sqrt n\right)$ 的,我同学用这个方法过了,但是我常数写大了一丢丢,System Test 的时候 TLE 了。。。

我猜测 vector 是通过打死亡标记 + 定期重构实现根号删除的。

UPD:vector 只是常数小而已,可能用了一些指令集之类的东西,但不是根号的。

显然,可用使用平衡树优化至 $\mathcal O\left(n \log n\right)$。

D

暂时鸽了。

E1

赛时想的是把序列平分成 $3$ 段,结果发现不行,原来分成 $4$ 段就行了啊啊啊啊啊。。。。

我们把 $s$ 平分成 $4$ 份,$s_1, s_2, s_3$ 和 $s_4$。然后询问 $\left\{s_1 \cup s_2\right\}$ 和 $\left\{s_1 \cup s_3\right\}$。

然后,我们分类讨论:

  1. 返回 N, N,发现 $x$ 一定不在 $s_1$ 里。
  2. 返回 N, Y,发现 $x$ 一定不在 $s_2$ 里。
  3. 返回 Y, N,发现 $x$ 一定不在 $s_3$ 里。
  4. 返回 Y, Y,发现 $x$ 一定不在 $s_4$ 里。

一直重复这个操作知道 $s$ 里的元素个数小于等于 $4$。

这样 $s$ 的大小每次会变成原来的 $\dfrac34$,通过计算发现最多通过 $76$ 次询问可以缩小至 $s$ 的大小到 $4$,然后暴力询问 $4$ 次,确定最终答案。题目给了 $82$ 次询问,绰绰有余。

E2

不会。

F

乱搞。
首先,离散化,给每个取值都随机一个值,然后我们在把一段区间里的权值加起来,得到 $h_{l, r}$,则如果一个区间里的每个数的出现次数都是 $k$ 的倍数,则 $h_{l, r}$ 也必然是 $k$ 的倍数。反之可能不是。所以,当 $k = 2$ 时,有 $\dfrac12$ 的概率检测错误,但是如果我们对于每个数使用 $p$ 个同的随机值,这样对于 $k = 2$ 检测错误的概率就是 $\dfrac1{2^p}$。使用树状数组或线段树维护 $h_{l, r}$。

G

不会。

代码

  • F

    // Please submit with C++14! It's best to use C++20 or higher version.
    constexpr bool __MTCS__ = 0;  // Spectre (n@rbtr.ee)
    #ifndef LOCAL                 // By rbtree (https://rbtr.ee)
    #pragma region HEAD           // DO OR DIE
    #endif
    #include <algorithm>
    #include <array>
    #include <bitset>
    #include <cmath>
    #include <cstring>
    #include <functional>
    #include <iostream>
    #include <list>
    #include <map>
    #include <numeric>
    #include <queue>
    #include <random>
    #include <set>
    #include <unordered_map>
    #include <utility>
    #include <vector>
    #ifdef ___RB_DEBUG___
    #include "rb_debug.h"
    #else
    #define dbg(...)
    #endif
    #define ra (scanf("%lld", &la), la)
    #define se(exp) exp.begin(), exp.end()
    #define LIKELY(exp) __builtin_expect(bool(exp), 1)
    #define UNLIKELY(exp) __builtin_expect(bool(exp), 0)
    
    typedef long long tp;
    using namespace std;
    void __Cored__(tp);
    tp la;
    
    signed main(/* >_< */) {
    for (static tp __TCS__ = __MTCS__ ? ra : 1, __NOW__ = 0; __NOW__ < __TCS__;
         __Cored__(++__NOW__)) {
    }
    return 0;
    }
    
    #ifndef LOCAL
    #pragma endregion HEAD
    #endif
    
    ////////////////////////////////////////////////////////////////////////////////
    
    constexpr tp c_P = 33, c_N = 3e5 + 3, c_LIM = 1e9 + 7;
    
    tp a[c_N];
    unordered_map<tp, tp> xid;
    tp t[c_P][c_N];
    tp c[c_P][c_N * 2];
    
    void modify(tp x, tp y, tp k) {
    while (y < c_N) {
      t[x][y] += k;
      y += y & -y;
    }
    }
    
    tp query(tp x, tp y) {
    tp tar = 0;
    while (y) {
      tar += t[x][y];
      y -= y & -y;
    }
    return tar;
    }
    
    void __Cored__([[maybe_unused]] tp __TID__) {
    tp n = ra, m = ra;
    mt19937 rnd(__builtin_ia32_rdtsc() % c_LIM);
    for (tp i = 1; i <= n; ++i) {
      a[i] = ra;
      if (!xid[la]) {
        xid[la] = xid.size() + 1;
        for (tp j = 0; j < c_P; ++j) c[j][xid[la]] = rnd();
      }
      for (tp j = 0; j < c_P; ++j) modify(j, i, c[j][xid[la]]);
    }
    while (m--) {
      if (ra == 1) {
        tp i = ra, x = ra;
        if (!xid[x]) {
          xid[x] = xid.size() + 1;
          for (tp j = 0; j < c_P; ++j) c[j][xid[x]] = rnd();
        }
        for (tp j = 0; j < c_P; ++j) modify(j, i, c[j][xid[x]] - c[j][xid[a[i]]]);
        a[i] = x;
      } else {
        bool f = 1;
        tp l = ra - 1, r = ra, k = ra;
        for (tp j = 0; j < c_P; ++j) {
          if ((query(j, r) - query(j, l)) % k) {
            f = 0;
            break;
          }
        }
        puts(f ? "YES" : "NO");
      }
    }
    }
    
    //*/

暂无评论

发表评论