虚拟位置映射(标签鸽

有 N 只鸽子,标号为 1, 2, ..., N,和 N 个巢穴,标号为 1, 2, ..., N。

初始时,鸽子 i(1≤i≤N)在巢穴 i 中。

你将对这些鸽子执行 Q 次操作。

操作有三种类型:

类型 1:给定整数 a 和 b(1≤a≤N,1≤b≤N)。将鸽子 a 从当前所在的巢穴中取出,移到巢穴 b 中。类型 2:给定整数 a 和 b(1≤a<b≤N)。将巢穴 a 中的所有鸽子移到巢穴 b 中,同时将巢穴 b 中的所有鸽子移到巢穴 a 中。这两个移动是同时进行的。类型 3:给定整数 a(1≤a≤N)。鸽子 a 报告它当前所在的巢穴标号。

按类型 3 操作给出的顺序,输出每个类型 3 操作的结果。

如果尝试用朴素的方式维护诸如 p2b [i] :=(鸽子 i 当前所在的巢穴编号)这样的信息,那么第二种类型的操作就需要对许多鸽子执行操作,因此很难在时间限制内完成。

相反,我们可以考虑引入虚拟的 "标签鸽"

核心思路

通过三个数组维护鸽子、标签鸽、巢穴之间的映射关系,避免了类型 2 操作中 "移动所有鸽子" 的耗时操作。

  • 标签鸽:虚拟的 "标记物",用于间接表示巢穴的逻辑关系,交换标签鸽即可等效于交换两个巢穴的所有鸽子(但无需实际移动)。
  • 映射关系:用三个数组记录位置映射,通过更新映射而非实际移动元素来处理操作。

数组定义与初始化

假设巢穴、鸽子、标签鸽的编号均为 1~N(代码中用 0~N-1 存储,最后加 1 转换为 1 基编号)。

  1. box_to_label[i]

    • 含义:巢穴 i(0 基)中当前存在的标签鸽编号(0 基)。
    • 初始化:iota 函数将其初始化为 [0,1,2,...,N-1],即初始时巢穴 i 中有标签鸽 i
  2. label_to_box[i]

    • 含义:标签鸽 i(0 基)当前所在的巢穴编号(0 基)。
    • 初始化:[0,1,2,...,N-1],即初始时标签鸽 i 在巢穴 i 中。
  3. pigeon_to_box[i]

    • 含义:真实鸽子 i(0 基)当前所在的巢穴编号(0 基)。
    • 初始化:[0,1,2,...,N-1],即初始时鸽子 i 在巢穴 i 中。

操作解析

类型 1 操作:移动鸽子 a 到巢穴 b
  • 输入:1 a ba 是鸽子编号,b 是目标巢穴编号,均为 1 基)。

  • 逻辑:鸽子 a 需要移动到 "标签鸽 b 所在的巢穴"(因为标签鸽 b 代表巢穴 b 的逻辑位置)。代码中:

    复制代码
    pigeon_to_box[a-1] = label_to_box[b-1];  // a-1 转换为 0 基鸽子编号,b-1 转换为 0 基标签鸽编号

    即更新鸽子 a 的位置为标签鸽 b 所在的巢穴。

类型 2 操作:交换巢穴 ab 中的所有鸽子
  • 输入:2 a bab 是巢穴编号,均为 1 基)。
  • 逻辑:无需移动真实鸽子,只需交换标签鸽 ab 的位置,即可等效于交换两个巢穴的所有鸽子。代码中分为两步:
    1. 交换标签鸽 ab 所在的巢穴:

      复制代码
      swap(label_to_box[a-1], label_to_box[b-1]);  // 标签鸽 a 和 b 的位置互换
    2. 同步更新巢穴中对应的标签鸽(维护 box_to_labellabel_to_box 的一致性):

      复制代码
      swap(box_to_label[label_to_box[a-1]], box_to_label[label_to_box[b-1]]);

      此时,label_to_box[a-1] 是交换后标签鸽 a 所在的巢穴,label_to_box[b-1] 是交换后标签鸽 b 所在的巢穴。交换这两个巢穴对应的标签鸽,确保 box_to_label 正确记录 "巢穴→标签鸽" 的映射。

类型 3 操作:查询鸽子 a 所在的巢穴编号
  • 输入:3 aa 是鸽子编号,1 基)。

  • 逻辑:鸽子 a 所在的巢穴中,当前的标签鸽编号即为该巢穴的逻辑编号(因为标签鸽代表巢穴的标识)。代码中:

    复制代码
    // 1. 找到鸽子 a 所在的巢穴:pigeon_to_box[a-1](0 基)
    // 2. 找到该巢穴中当前的标签鸽:box_to_label[巢穴编号](0 基)
    // 3. 转换为 1 基编号输出
    cout << box_to_label[pigeon_to_box[a-1]] + 1 << '\n';

    #include <iostream>
    #include <vector>
    #include <numeric>
    using namespace std;

    int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    复制代码
      int N, Q;
      cin >> N >> Q;
      
      vector<int> b2l(N), l2b(N), p2b(N);
      iota(begin(b2l), end(b2l), 0);
      iota(begin(l2b), end(l2b), 0);
      iota(begin(p2b), end(p2b), 0);
      
      while (Q--) {
          int t, a, b;
          cin >> t;
          if (t == 1) {
              cin >> a >> b;
              p2b[a-1] = l2b[b-1];
          } else if (t == 2) {
              cin >> a >> b;
              swap(l2b[a-1], l2b[b-1]);
              swap(b2l[l2b[a-1]], b2l[l2b[b-1]]);
          } else {
              cin >> a;
              cout << b2l[p2b[a-1]] + 1 << '\n';
          }
      }
      return 0;

    }

相关推荐
Yue丶越2 小时前
【C语言】深入理解指针(二)
c语言·开发语言·数据结构·算法·排序算法
m0_748248022 小时前
C++中的位运算符:与、或、异或详解
java·c++·算法
沐浴露z2 小时前
详解【限流算法】:令牌桶、漏桶、计算器算法及Java实现
java·算法·限流算法
王哈哈^_^2 小时前
【完整源码+数据集】草莓数据集,yolov8草莓成熟度检测数据集 3207 张,草莓成熟度数据集,目标检测草莓识别算法系统实战教程
人工智能·算法·yolo·目标检测·计算机视觉·视觉检测·毕业设计
程序员东岸3 小时前
数据结构杂谈:双向链表避坑指南
数据结构·链表
songyuc3 小时前
《A Bilateral CFAR Algorithm for Ship Detection in SAR Images》译读笔记
人工智能·笔记·计算机视觉
油泼辣子多加3 小时前
【实战】自然语言处理--长文本分类(3)HAN算法
算法·自然语言处理·分类
01100001乄夵3 小时前
第二课:时序逻辑入门-零基础FPGA闯关教程
经验分享·笔记·学习方法
Shinom1ya_3 小时前
算法 day 46
数据结构·算法