惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
CXSECURITY Database RSS Feed - CXSecurity.com
K
Kaspersky official blog
A
Arctic Wolf
Attack and Defense Labs
Attack and Defense Labs
L
LINUX DO - 热门话题
N
News | PayPal Newsroom
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
L
Lohrmann on Cybersecurity
PCI Perspectives
PCI Perspectives
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
The Last Watchdog
The Last Watchdog
B
Blog RSS Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
W
WeLiveSecurity
Know Your Adversary
Know Your Adversary
博客园 - Franky
T
Tenable Blog
T
Tailwind CSS Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Help Net Security
Help Net Security
WordPress大学
WordPress大学
T
The Exploit Database - CXSecurity.com
www.infosecurity-magazine.com
www.infosecurity-magazine.com
博客园 - 司徒正美
阮一峰的网络日志
阮一峰的网络日志
D
Darknet – Hacking Tools, Hacker News & Cyber Security
H
Heimdal Security Blog
TaoSecurity Blog
TaoSecurity Blog
S
Security Affairs
J
Java Code Geeks
小众软件
小众软件
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Apple Machine Learning Research
Apple Machine Learning Research
NISL@THU
NISL@THU
O
OpenAI News
The Cloudflare Blog
月光博客
月光博客
Google Online Security Blog
Google Online Security Blog
V
V2EX
罗磊的独立博客
美团技术团队
博客园 - 三生石上(FineUI控件)
Security Latest
Security Latest
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
C
Cyber Attacks, Cyber Crime and Cyber Security
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Cyberwarzone
Cyberwarzone
L
LINUX DO - 最新话题
Hacker News - Newest:
Hacker News - Newest: "LLM"
大猫的无限游戏
大猫的无限游戏

Shiroha白羽的博客

Golang 踩坑 —— interface 为参数的时候传 nil 指针 Codeforces Round 925 (Div. 3) Codeforces Round 924 (Div. 2) Codeforces Round 923 (Div. 3) Codeforces Round 922 (Div. 2) Codeforces Round 921 (Div. 2) Educational Codeforces Round 161 (Rated for Div. 2) Codeforces Round 920 (Div. 3) Codeforces Round 919 (Div. 2) Hello 2024 Good Bye 2023 Codeforces Round 918 (Div. 4) 个人备份的常用 macOS 清理命令 Codeforces Round 917 (Div. 2) Pinely Round 3 (Div. 1 + Div. 2) Educational Codeforces Round 160 (Rated for Div. 2) Codeforces Round 915 (Div. 2) Codeforces Round 914 (Div. 2) Codeforces Round 913 (Div. 3) Educational Codeforces Round 159 (Rated for Div. 2) Codeforces Round 912 (Div. 2) Codeforces Round 911 (Div. 2) CodeTON Round 7 (Div. 1 + Div. 2, Rated, Prizes!) Educational Codeforces Round 158 (Rated for Div. 2) Codeforces Round 910 (Div. 2) Codeforces Round 909 (Div. 3) Codeforces Round 908 (Div. 2) Educational Codeforces Round 157 (Rated for Div. 2) C++自定义的字面量 Codeforces Round 907 (Div. 2) Codeforces Round 916 (Div. 3) 关于 LRU map 的一些灵感 2023 杭州站 ICPC 现场赛 反复横跳的 Clang-Tidy(cert-dcl21-cpp) Codeforces Round 906 (Div. 2) 一段奇怪的 CPP 代码 Codeforces Round 905 (Div. 3) Codeforces Round 904 (Div. 2) Codeforces Round 903 (Div. 3) Educational Codeforces Round 156 (Rated for Div. 2) Codeforces Round 902 (Div. 2, based on COMPFEST 15 - Final Round) Codeforces Round 901 (Div. 2) Codeforces Round 900 (Div. 3) Codeforces Round 899 (Div. 2) Educational Codeforces Round#155 (Div. 2) Codeforces Round 898 (Div. 4) CodeTON Round 6 (Div. 2) Codeforces Round 897 (Div. 2) Codeforces Round 896 (Div. 2) Codeforces Round 887 (Div. 2) Codeforces Round 895 (Div. 3) 左值-右值-将亡值 blog.mauve.icu Pinely Round 2 (Div. 1 + Div. 2) Harbour.Space Scholarship Contest 2023-2024 (Div. 1 + Div. 2) Codeforces Round 894 (Div. 3) Codeforces Round 888 (Div. 3) Educational Codeforces Round#153 (Div. 2) Codeforces Round 893 (Div. 2) OTPAUTH,两步验证中的通用协议 Codeforces Round 892 (Div. 2) Codeforces Round 891 (Div. 3) Codeforces Round 890 (Div. 2) Educational Codeforces Round#152 (Div. 2) blog.mauve.icu Java Script 的 null 和 undefined 随想 记一次 SQL LEFT JOIN 没有得到预期结果的错误 Codeforces Round#789(Div. 2) GCC/G++ 预编译头性能优化 使用 Junit5 和 Mockito 实现 SpringBoot 的单元测试最优美的解决方案 centOS 防火墙 docker-compse 的问题 C++ 语言实现动态变化的线程池 Codeforces Round#744 (Div. 3) 计算机图形学 Windows 通过网络访问 WSL2 原生 JavaScript 实现图片裁剪 面试复习(计算机图形学) 面试复习(算法) Codeforces Round#706(Div. 2)-Let's Go Hiking 面试复习(Java) 面试复习(Git) 面试复习(Linux) 面试复习(数据库) 面试复习(计算机网络) 面试复习(操作系统) 面试复习(C++) Codeforces Round#699 (Div. 2) 清理 WSL2 的磁盘占用 Codeforces Round#697 (Div. 3) Windows 下的 NTFS 驱动器索引 BUG 计算机网络复习 记一次 Navicat 连接 MySQL 一直报认证错误(Access denied) 计算机网络实验复习 WSL1 使用 Docker 一直无法启动 2020牛客暑期多校训练营(第三场)D-Points Construction Problem——构造 2020牛客暑期多校训练营(第三场)E-Two Matchings——复杂思维与简单dp 2020牛客暑期多校训练营(第二场)I-Interval——最大流转对偶图求最短路 Educational Codeforces Round 80 D. Minimax Problem——二分+二进制处理 Codeforces Round 606 E. Two Fairs——图论 Codeforces Round 612 (Div. 2) C. Garland——DP
Codeforces Round 1101 (Div. 2)
Shiroha · 2026-06-07 · via Shiroha白羽的博客

因为如果首个位置要留给后面的 I 人,那么这个 A 人就得放弃(前面没有非空的有空桌子)
那为什么不选择让这个 A 人坐下,放弃后面那个 I 人,这样这个 A 人和 I 人之前的 E 人就有机会找到座位
这两个方案代价一致,但是带来收益完全可以被覆盖,故上面这条成立

这是一个汉诺塔题,但是,正常情况下,每一个块必须是上面没有其他块的时候才可以移动,而这里变成了:
上面必须恰好要有 $a_i$ 块的时候,$i$ 才能移动,且仅移动 $i$ 本身(不移动其上面的部分)

我们定义当前汉诺塔有三个柱子:base(当前所在的), tmp(用来华容道的), target(目标移动到的)
对于有 $n$ 个块的汉诺塔,我们可以得到两个显而易见的结论:

  1. 对于方块 $n$,无论它在哪,并不影响其他的方块移动:因为它是最大的那个方块,任何方块都可以放到它上面,它相当于基座
  2. 汉诺塔的三座塔等价,即在任何时候,如果 $\exists$ 一种操作,可以将 $x$ 高度的汉诺塔从 base 移动到 target,那么必然存在几乎相同的操作将其移动到 tmp

所以我们可以得到如下的汉诺塔递推公式:

  • 假定有一种方式,可以将 $n - 1$ 的汉诺塔,从 base 移动到 target
  • 那么对于 $n$ 而言,可以先将 $n - 1$ 按照之前的方式移动到 tmp
  • 然后将 $n$ 移动到 target
  • 最后将之前移动到 tmp 的 $n - 1$ 再执行一次 $n - 1$ 的汉诺塔操作,移动到 target,即块 $n$ 上
  • 得到汉诺塔的递归公式:$a_i = 2 \times a_{i-1} + 1$
  • 其中 $a_1 = 1$

通常情况下,我们会使用递推公式直接计算通项公式或者直接算出目标值,事实上,我们仍然可以使用递归来真实计算

这里由于需要考虑到拆分(需要保留一些块在当前块上,当前块才可以移动)
所以我们定义一个新的 $g(i, j)$ 表示:初始且保持 $1 \to (j - 1)$ 在 tmp 的情况下,让 $j \to i$ 这 $i - j + 1$ 块从 base 移动到 target 需要的步数

此时 A 块表示的就是 $1 \to (j - 1)$ 块部分,而 B + C + X 表示 $j \to i$ 部分
其中 X 表示就是第 $i$ 行, C 表示 $a_i$ 部分,而 B 就是多出来的部分

$$ \begin{matrix} A \to target \\ B \to tmp \\ A \to tmp \\ X \to target \\ C \to target \\ A \to base \\ B \to target\\ A \to tmp \end{matrix} $$

其中 X 表示就是第 $i$ 行,此时 C + X 块表示的就是 $j \to i$ 块部分
而 A + C 恰好为 $a_i$,A + B 为 $1 \to (j - 1)$,B 为剩余部分

$$ \begin{matrix} A \to base \\ X \to target \\ A \to tmp \\ C \to target \end{matrix} $$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
using namespace std;

void solve() {
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int n;
cin >> n;
vector<int> v(n);
for (int i = 0; i < n; ++i) cin >> v[i];

bool ok = true;
for (int i = 0; i < n; ++i) if (v[i] > i) ok = false;
if (!ok) {
printf("NO\n");
continue;
}

vector<tuple<int, int, int>> ans;
ans.reserve(1 << (n + 1));
// if [j, i] is on base, [0, (j - 1)] on tmp, make [j, i] into target and [0, (j - 1)] into base
int deep = 0;
const function<void(int, int, int, int, int)> mv = [&](int i, int j, int base, int target, int tmp) {
if (i < j) return;
++deep;
// if (i != j) cerr << deep << ' ' << i << ' ' << j << ' ' << base << ' ' << target << endl;
if (i == j && v[i] == 0) {
ans.emplace_back(i, base, target);
} else if (v[i] == 0) {
mv(j - 1, 0, tmp, target, base);
mv(i - 1, j, base, tmp, target);
mv(j - 1, 0, target, tmp, base);
ans.emplace_back(i, base, target);
mv(j - 1, 0, tmp, base, target);
mv(i - 1, j, tmp, target, base);
mv(j - 1, 0, base, tmp, target);
} else if (i - j >= v[i]) {
mv(j - 1, 0, tmp, target, base);
mv(i - 1 - v[i], j, base, tmp, target);
mv(j - 1, 0, target, tmp, base);
// cerr << "MOV" << ans.size() << ' ' << i << ' ' << base << ' ' << target << endl;
ans.emplace_back(i, base, target);
mv(i - 1, i - v[i], base, target, tmp);
mv(j - 1, 0, tmp, base, target);
mv(i - 1 - v[i], j, tmp, target, base);
mv(j - 1, 0, base, tmp, target);
} else {
const int need = v[i] - (i - j);
mv(need - 1, 0, tmp, base, target);
ans.emplace_back(i, base, target);
mv(need - 1, 0, base, tmp, target);
mv(i - 1, j, base, target, tmp);
}
--deep;
};

mv(n - 1, 0, 1, 3, 2);
// merge
int r = 0;
for (int i = 1; i < ans.size(); ++i) {
if (get<0>(ans[i]) != get<0>(ans[r])) {
++r;
ans[r] = ans[i];
} else {
ans[r] = {get<0>(ans[r]), get<1>(ans[r]), get<2>(ans[i])};
if (get<1>(ans[r]) == get<2>(ans[r])) --r;
}
}

printf("YES\n%d\n", r + 1);
for (int i = 0; i <= r; ++i) {
auto [a, b, c] = ans[i];
printf("%d %d %d\n", a + 1, b, c);
}
}
}