【Ynoi2018】天降之物

【Ynoi2018】天降之物

题意

给定一个长为 \(n\) 的序列 \(a\),支持两种操作:

  1. 将所有 \(a_p = x\) 修改为 \(y\)

  2. 查询 \(\min(|i-j|)\),满足 \(a_i = x \and a_j = y\) 或者 \(a_i = y \and a_j = x\)

题解

考虑序列分块,首先考虑块内贡献,设块长为 \(B\),由于分块的 \(B\) 一般为根号级别,直接将一个块内数离散化,预处理一个数在块内出现的第一个位置和最后一个位置,记录 \(ins_{i,j}\) 表示 \((i, j)\) 的答案。

预处理是 \(O(\frac{n}{B}(B^2 + B\log B))\) 的复杂度。

接着先思考询问,一个块内的处理完了,直接查,如果不在一个块,一定是前一个在块最后,后一个在块开头。前面处理的直接用上,注意答案不一定在相邻的两个块内(卡了很久)。

然后是修改,分类讨论一下

  1. 如果 \(x\) 没出现,直接跳过。
  2. 如果 \(y\) 没出现,显然总颜色数不变,直接让 \(y\) 继承 \(x\) 的信息即可。
  3. 如果 \(x\)\(y\) 都出现,对于 \(ins\) 我们重新遍历一遍块更新答案即可。另外东西直接取 \(\min\) 或者 \(max\) 即可。由于每次修改会让一个块少一个颜色,所以总复杂度是 \(O(n\sqrt n)\) 的。

注意修改完要把 \(x\) 在这个块内标记为不存在。

注意一点细节卡个常就过了。

#include <bits/stdc++.h>
namespace FileHeader {
  using int16 = int16_t;
  using int32 = int32_t;
  using int64 = int64_t;
  using uint32 = uint32_t;
  using uint64 = uint64_t;
  #define ep emplace
  #define eb emplace_back
  #define all(x) x.begin(), x.end()
  FILE* fin, * fout, * ferr;
  int32 read() {
    int32 t = 0, f = 0;
    char ch = fgetc(fin);
    for (; !isdigit(ch); ch = fgetc(fin)) f ^= (ch == '-');
    for (; isdigit(ch); ch = fgetc(fin)) t = (t << 1) + (t << 3) + (ch ^ 48);
    return f ? -t : t;
  }
  class Iterator {
    public:
      Iterator(int32 _val = 0): _val(_val) {}
      bool operator !=(const Iterator &other) const { return this->_val != other._val; }
      int32 operator *() { return this->_val; }
      int32 operator ++() { return ++this->_val; }
    private:
      int32 _val;
  };
  class Range {
    public:
      Range(int32 _l = 0, int32 _r = 0): _begin(_l), _end(_r + 1) {}
      Iterator begin() { return Iterator(this->_begin); }
      Iterator end() { return Iterator(this->_end); }
    private:
      int32 _begin, _end;
  };
}
using namespace FileHeader;
namespace Solution_Of_P5397 {
  static const int32 N = 100010, B = 255, M = N / B + 10;
  static const int32 inf32 = 0x3f3f3f3f;
  int32 n, m, bl;
  int32 a[N], b[N];
  int32 L[M], R[M], len[M];
  int16 ins[N][M];
  int16 inp[N][M];
  int32 fir[N], sec[N];
  template<typename T>
  inline void cmin(T &x, T y) { return x = (x < y ? x : y), void(); }
  template<typename T>
  inline void cmax(T &x, T y) { return x = (x > y ? x : y), void(); }
  inline void init(int32 bl, int32 l, int32 r) {
    L[bl] = l, R[bl] = r;
    int32 P = R[bl - 1];
    std::vector<int32> numric;
    for (auto i : Range(l, r)) numric.eb(a[i]);
    std::sort(all(numric), [&](int32 a, int32 b) { return a < b; });
    numric.erase(std::unique(all(numric)), numric.end());
    len[bl] = static_cast<int32>(numric.size());
    for (int32 i = l; i <= r; ++i) {
      b[i] = std::lower_bound(all(numric), a[i]) - numric.begin() + 1;
      inp[a[i]][bl] = b[i];
    }
    for (int32 i = r; i >= l; --i) fir[P + b[i]] = i;
    for (int32 i = l; i <= r; ++i) sec[P + b[i]] = i;
    for (int32 i = 1; i <= len[bl]; ++i)
      std::memset(ins[P + i], 64, (len[bl] + 1) << 1);
    for (auto i : Range(l, r))
      for (auto j : Range(i + 1, r)) {
        int32 a1 = inp[a[i]][bl], a2 = inp[a[j]][bl];
        if (a1 > a2) std::swap(a1, a2);
        cmin(ins[P + a1][a2], int16(j - i));
      }
    return void();
  }
  inline int32 trans(int16 x) {
    if (x == 0x3f3f) return 0x3f3f3f3f;
    return static_cast<int32>(x);
  }
  inline int32 query(int32 x, int32 y) {
    if (x == y) {
      for (auto i : Range(1, bl))
        if (inp[x][i]) return 0;
      return 0x3f3f3f3f;
    }
    int32 ans = inf32;
    int32 lst1 = -inf32, lst2 = -inf32;
    for (auto i : Range(1, bl)) {
      int16 a1 = inp[x][i], a2 = inp[y][i];
      int32 P = R[i - 1];
      if (a1) cmin(ans, fir[P + a1] - lst2);
      if (a2) cmin(ans, fir[P + a2] - lst1);
      if (a1) lst1 = sec[P + a1];
      if (a2) lst2 = sec[P + a2];
      if (a1 > a2) std::swap(a1, a2);
      if (a1 && a2) cmin(ans, trans(ins[P + a1][a2]));
    }
    return ans;
  }
  inline void modify1(int32 bl, int32 x, int32 y) {
    inp[y][bl] = inp[x][bl];
    inp[x][bl] = 0;
    return void();
  }
  inline void modify2(int32 bl, int32 x, int32 y) {
    int16 a1 = inp[x][bl], a2 = inp[y][bl];
    int32 P = R[bl - 1];
    cmin(fir[P + a2], fir[P + a1]);
    cmax(sec[P + a2], sec[P + a1]);
    fir[P + a1] = sec[P + a1] = 0;
    if (a1 < a2) {
      for (auto i : Range(1, a1)) cmin(ins[P + i][a2], ins[P + i][a1]);
      for (auto i : Range(a1 + 1, a2)) cmin(ins[P + i][a2], ins[P + a1][i]);
      for (auto i : Range(a2 + 1, len[bl])) cmin(ins[P + a2][i], ins[P + a1][i]);
    } else {
      for (auto i : Range(1, a2)) cmin(ins[P + i][a2], ins[P + i][a1]);
      for (auto i : Range(a2 + 1, a1)) cmin(ins[P + a2][i], ins[P + i][a1]);
      for (auto i : Range(a1 + 1, len[bl])) cmin(ins[P + a2][i], ins[P + a1][i]);
    }
    inp[x][bl] = 0;
    return void();
  }
  inline void modify(int32 x, int32 y) {
    if (x == y) return void();
    for (auto i : Range(1, bl)) {
      if (!inp[x][i]) continue;
      if (!inp[y][i]) modify1(i, x, y);
      else modify2(i, x, y);  
    }
    return void();
  }
  inline void main() {
    fin = stdin, fout = stdout, ferr = stderr;
    // fin = fopen("data.in", "r");
    // fout = fopen("data.out", "w");
    n = read(), m = read();
    for (auto i : Range(1, n)) a[i] = read();
    bl = (n - 1) / B + 1;
    for (auto i : Range(1, bl)) init(i, (i - 1) * B + 1, std::min(n, i * B));
    for (auto t : Range(1, m)) {
      static int32 op, x, y, lastans = 0;
      op = read(), x = read() ^ lastans, y = read() ^ lastans; 
      if (op == 1) modify(x, y);
      if (op == 2) {
        lastans = query(x, y);    
        if (lastans == inf32) lastans = 0, fputs("Ikaros\n", fout);
        else fprintf(fout, "%d\n", lastans);
      }  
    }
    return void();
  }
}
signed main() { return Solution_Of_P5397::main(), 0; }
posted @ 2023-09-24 18:47  xxcxu  阅读(2)  评论(0编辑  收藏  举报