<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans">
  <id>https://blog.lnkkerst.me</id>
  <title type="text">lnkkerst&#39;s blog</title>
  <subtitle type="text">lnkkerst 的个人博客：算法竞赛题解、折腾记录与读书笔记。</subtitle>
  <updated>2022-08-06T07:50:21.000Z</updated>
  <link href="https://blog.lnkkerst.me/" rel="alternate" type="text/html"/>
  <link href="https://blog.lnkkerst.me/atom.xml" rel="self" type="application/atom+xml"/>
  <logo>https://blog.lnkkerst.me/favicon.ico</logo>
  <generator>Astro</generator>
  <author>
    <name>lnkkerst</name>
    <email>lnkkerst04@gmail.com</email>
    <uri>https://lnkkerst.me</uri>
  </author>
  <rights>CC BY-NC-SA 4.0</rights>
  <entry>
    <id>https://blog.lnkkerst.me/posts/record-a-failure-to-install-openbsd</id>
    <title type="text">记录一次安装 OpenBSD 翻车</title>
    <link href="https://blog.lnkkerst.me/posts/record-a-failure-to-install-openbsd" rel="alternate" type="text/html"/>
    <updated>2022-08-06T07:50:21.000Z</updated>
    <published>2022-08-06T07:50:21.000Z</published>
    <author><name>lnkkerst</name><email>lnkkerst04@gmail.com</email><uri>https://lnkkerst.me</uri></author>
    <content type="text">之前一直想尝试 FreeBSD，无奈当时 FreeBSD 对 AX200 的支持还是不太友好(起码我的设备是这样)，这次闲来无事，准备尝试一下据说早就支持 AX200 的 OpenBSD。
然后翻车了。
安装准备
抱着不作死不休和“我根本没有重要的数据”的想法，我没有进行任何避险操作，草草的 btrfs subv snapshot 过后就开始安装，没有备份昨天晚上那几个还没 push 的 commit，备份完的分区表放在了原来磁盘的分区里(wssb)。
简单下载刻录镜像(没有校验)，我便重启电脑，连官方的文档都没有看就直接盲操。
安装
前面的几步挺顺利的，我也没有留图，当然这些都不重要。到了分区这一步，用的是 OpenBSD 的 fdisk，貌似和 Linux 下的不太一样？好，按 m 查看文档。哇好长的文档，按 j 往下翻。2k 屏幕一行一行翻页好卡啊，试试 &lt;C-d&gt;，哇，居然可以用。还是好卡(疯狂按)。
沃日，怎么翻页翻完了还能直接退出的，还多摁了几个 &lt;C-d&gt; 搁缓冲区哇 😐。
翻车
既然有自定义分区，那肯定也有全盘安装和自动分区，很不巧的是全盘安装的选项在第一个，多翻的那几页直接给我全盘安装 + 确认一条龙。
意识到不对劲的我赶紧看了下分区表，确实被干的稀碎。
我傻了，连图都忘了截。
亡羊补牢
新分区表建好后倒是没有再写入什么内容，但我原来 Linux 的分区是 LUKS+btrfs 的组合，感觉随便出点事就是数据火葬场。
Google 后找到了这个补救方法，这次可不敢不看文档了。
跟着老哥的操作倒是很顺利的找到了原来的分区的位置，建立好新分区修改好标识后，剩下的分区用 DiskGenius 很轻松就找回来了，不过接下来才是关键时刻，直接 btrfs scrub
应该是没救了(悲
好在 @home 子卷下的文件大部分都没事，也不知道什么原理。备份了 @home 子卷 和 /etc 分区后开始准备重装系统了。
恢复
因为原来使用的 Linux 发行版是 Gentoo，又十分不幸，之前构建好的 binpkgs 似乎无一幸免，重装过程只能说异常痛苦(其实也就是配置拉完然后编译了一夜)。
剩下的几个分区还没有测试，目前使用看来倒没发现有什么文件损坏，不过这些分区里面倒是真的没有重要文件就是了。
总结
其实感觉这种事发生概率还挺低的，最主要的还是我过于 sb 也不备份也不虚拟机测试也不看文档直接在主力机上尝试安装没接触过的系统，希望广大网友引以为戒(
其实在安装系统的前一天我就把家里旧电脑上的一块硬盘格式化成了 btrfs，打算拿来作备份。但第一次 btrfs send 实在是太耗时，嫌麻烦就没搞 😭。
从接触电脑到现在，这是我第二次在安装系统上翻车，只能说受到的教训还是太少了，没有真切的体会到备份的重要性，这次可算是吃了大亏。
可是我懒癌又犯了，除了受伤的电脑还有几台服务器要备份，手头上也没有什么储存介质能承受一次完整备份和后续的增量备份，只能说下次一定 🤕。</content>
    <category term="BSD"/>
    <category term="Linux"/>
  </entry>
  <entry>
    <id>https://blog.lnkkerst.me/posts/ccf-csp-25th-t4-solution</id>
    <title type="text">第 25 次 CCF CSP 认证 T4 通信系统管理 题解</title>
    <link href="https://blog.lnkkerst.me/posts/ccf-csp-25th-t4-solution" rel="alternate" type="text/html"/>
    <updated>2022-05-02T11:28:07.000Z</updated>
    <published>2022-05-02T11:28:07.000Z</published>
    <author><name>lnkkerst</name><email>lnkkerst04@gmail.com</email><uri>https://lnkkerst.me</uri></author>
    <content type="text">原题链接：通信系统管理。
这题思路还是挺好想的，就是考场上的时候我死活调不出来 😷。正好最近有网友问我这道题，才想起来给 A 了。
题目大意是有 n 台机器编号 1 到 n，每个机器和其它机器通信有一个额度，需要维护的操作：
增加和减少两台机器额度。
求和某台机器通信额度最大的机器，记做“主要通信对象”。
计算互相为主要通信对象（通信对）的对数。
计算和其他机器没有任何额度的机器（通信孤岛）的个数。
每个操作的数量级都是 10^5，要保证单次操作时间复杂度在 O(nlogn) 以内。
首先依靠前两种操作，后两种操作的结果都可以在进行操作 1 的过程中直接更新出来。操作 1、2 则是让我们动态维护区间最大值，可以用线段树，每台机器建一个线段树。注意直接完整建树空间爆炸，所以线段树要动态开点。另一种做法是直接上平衡树，这里偷点懒，直接拿 std::multiset 来用，已经够用了。
代码有注释～
#pragma GCC optimize(2) // 开 O2 优化，STL 重灾区
#include &lt;iostream&gt;
#include &lt;set&gt; // 明星选手
#include &lt;unordered_map&gt;
#include &lt;vector&gt;
using namespace std;
#define int long long // 额度会爆 int，这里偷个懒
struct Node {
int v, w; // 单个节点，ｖ 储存目标机器，w 储存额度
Node(int _v, int _w) : v(_v), w(_w) {}
// 排序根据题目要求，额度作为第一关键字升序，编号作为第二关键字降序
bool operator&lt;(const Node &amp;b) const {
if (this-&gt;w == b.w) {
return this-&gt;v &lt; b.v;
}
return this-&gt;w &gt; b.w;
}
};
struct Req { // 用来储存修改额度的请求
int u, v, x; // 和题目所述意义相同
Req(int _u, int _v, int _x) : u(_u), v(_v), x(_x) {}
};
int n, m; // 含义如题
vector&lt;multiset&lt;Node&gt;&gt; a; // 每台机器的伪平衡树
vector&lt;unordered_map&lt;int, decltype(a.front().begin())&gt;&gt;
b; // b[u][v] 储存机器 u 到机器 v 的额度在 a 中的迭代器（如果存在）
vector&lt;vector&lt;Req&gt;&gt; de; // de[i] 储存第 i 天失效的请求
int cntSingle, cntPair; // 储存通信孤岛和通信对的数量
// 查询机器 u 的主要通信对象
Node query(int u) {
if (a[u].empty()) {
return {0, 0};
}
return *(a[u].begin());
}
// 查询机器 u 是否在通信对里
bool hasPair(int u) {
int v = query(u).v;
if (v == 0) {
return false;
}
return query(v).v == u;
}
// 给机器 u 到机器 v 的通信额度增加 x （单向）
void add(int u, int v, int x) {
if (a[u].empty()) {
--cntSingle; // u 为通信孤岛时，add 操作后它一定不是通信孤岛
}
if (hasPair(u)) {
--cntPair; // 先把 u 从通信对里去除，操作结束后再看看是不是还在通信对里
}
auto it = b[u].find(v); // 找储存 u 和 v 通信额度的节点
if (it != b[u].end()) { // 找到了，修改
auto bf = (it-&gt;second)-&gt;w;
a[u].erase(it-&gt;second);
b[u].erase(it);
if (bf + x != 0) { // 额度不为 0 的时候才把节点插入 multiset
b[u][v] = a[u].insert(Node(v, bf + x));
}
} else { // 没找到，直接插入 multiset
b[u][v] = a[u].insert(Node(v, x));
}
if (a[u].empty()) {
++cntSingle; // 若 add 操作后 u 没有任何通信额度，那它一定是新增的通信孤岛
}
if (hasPair(u)) {
++cntPair;
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin &gt;&gt; n &gt;&gt; m;
a.resize(n + 1);
b.resize(n + 1);
de.resize(m + 1);
cntSingle = n;
for (int t = 1; t &lt;= m; ++t) {
for (const auto &amp;i : de[t]) { // 处理失效的请求
add(i.u, i.v, -i.x); // 两边都要减
add(i.v, i.u, -i.x);
}
int k;
cin &gt;&gt; k;
for (int i = 1; i &lt;= k; ++i) {
int u, v, x, y;
cin &gt;&gt; u &gt;&gt; v &gt;&gt; x &gt;&gt; y;
add(u, v, x); // 两边都要加
add(v, u, x);
if (t + y &lt;= m) { // 会用到的失效请求才记录
de[t + y].emplace_back(Req(u, v, x));
}
}
int l; // 以下含义如题
cin &gt;&gt; l;
for (int i = 1; i &lt;= l; ++i) {
int u;
cin &gt;&gt; u;
cout &lt;&lt; query(u).v &lt;&lt; endl;
}
int p, q;
cin &gt;&gt; p &gt;&gt; q;
if (p) {
cout &lt;&lt; cntSingle &lt;&lt; endl;
}
if (q) {
cout &lt;&lt; cntPair &lt;&lt; endl;
}
}
return 0;
}</content>
    <category term="CSP"/>
  </entry>
  <entry>
    <id>https://blog.lnkkerst.me/posts/neovim-lspconfig-config</id>
    <title type="text">Neovim + Lspconfig 配置</title>
    <link href="https://blog.lnkkerst.me/posts/neovim-lspconfig-config" rel="alternate" type="text/html"/>
    <updated>2022-04-25T07:50:17.000Z</updated>
    <published>2022-04-25T07:50:17.000Z</published>
    <author><name>lnkkerst</name><email>lnkkerst04@gmail.com</email><uri>https://lnkkerst.me</uri></author>
    <content type="text">折腾一下 nvim
github</content>
    <category term="nvim"/>
  </entry>
  <entry>
    <id>https://blog.lnkkerst.me/posts/nvim-study-notes</id>
    <title type="text">Nvim 学习笔记</title>
    <link href="https://blog.lnkkerst.me/posts/nvim-study-notes" rel="alternate" type="text/html"/>
    <updated>2022-03-12T14:25:44.000Z</updated>
    <published>2022-03-12T14:25:44.000Z</published>
    <author><name>lnkkerst</name><email>lnkkerst04@gmail.com</email><uri>https://lnkkerst.me</uri></author>
    <content type="text">跟着官网走～
刚发现这个和 vimtutor 内容是一样的而且 vimtutor 还有中文翻译，wssb
Tutor
Normal 模式下键入 :Tutor &lt;Enter&gt;
Lesson 0
狂按 &lt;ESC&gt; 返回 Normal 模式
所有指令在 Normal 模式下进行
Normal 模式下按下 u 撤销操作
Normal 模式下光标在链接处按下 &lt;Enter&gt; 可以打开链接
K 查询光标所在单词读应手册
:help 后面可以跟好多东西，多试一试吧，不要忘记 &lt;Enter&gt; !
Lesson 1
Lesson 1.1: 移动光标
h、j、k、l 分别对应左、下、上、右
Lesson 1.2: 退出 Vim/Nvim
:q! &lt;Enter&gt; 不保存并退出（ q 退出，! 强制）
Lesson 1.3: 删除内容
x 删除光标对应字符
Lesson 1.4: 插入内容
i 在光标前插入内容（进入 Insert 模式）
Lesson 1.5: 在行尾添加内容
A 在当前行行尾添加内容（进入 Insert 模式）
Lesson 1.6: 编辑一个文件
:wq &lt;Enter&gt; 来保存一个文件并退出 Vim/Nvim
打开终端，$ nvim /path/to/your/file 使用 Nvim 编辑文件
🌿 怎么原文到这里有个 Lesson 1 的总结，前面看了这么多感觉自己被骗了 w(ﾟ Д ﾟ)w
Lesson 2
Lesson 2.1: 删除指令
dw 从光标处开始向后删除直到遇到下一个单词
Lesson 2.2: 更多删除指令
d$ 从光标处开始删除直到行尾的内容
Lesson 2.3: 组合
d + motion，d 表示删除操作，motion 是光标移动的操作，和 d 结合起来就是删除光标移动经过的内容
w : 光标移动到下一个单词开头，dw 删除直到下一个单词开头
e : 光标移动到当前单词结尾，de 删除当前单词
$ : 光标移动到行尾，d$ 将光标当前位置到结尾的内容全部删除（注意和前两种不同，会将行尾的字符一并删除）
Lesson 2.4: 给操作指定重复次数
移动操作前加上数字，如 2w、3e
Lesson 2.5: 多次删除
类似 d2w
Lesson 2.6: 和整行有关的操作
dd 删除一整行
2dd 删除两行
Lesson 2.7: 撤销和重做
u 撤销上一次操作
U 恢复当前行
&lt;C-r&gt; 重做
Lesson 3
Lesson 3.1: PUT 命令
按下 p 将上次删除的内容插入到光标之后
Lesson 3.2: REPLACE 命令
按下 rx 将光标处内容替换为 x
Lesson 3.3: CHANGE 操作
按下 ce 来替换到当前单词词尾的内容
Lesson 3.4: 更多 CHANGE 操作
c [number] motion
Lesson 4
Lesson 4.1 光标位置和文件状态
按下 &lt;C-g&gt; 在页面下方显示文件名和光标在当前文件位置信息。
按下 &lt;C-g&gt; 后，按下 G 可以移动到文件最后一行，按下 gg 可以移动到文件第一行
输入行数（会在页面底部显示）后再按下 G 可以跳转到指定行
Lesson 4.2 查找指令
输入 / 后跟内容可以进行查找，按下 &lt;Enter&gt;
继续按下 n 向下查找，N 向上查找
反向查找，使用 ? 而不是 /
按下 &lt;C-o&gt; 返回查找前的位置，&lt;C-i&gt; 前进
Lesson 4.3 括号匹配
将光标移动到 ()、[]、{} 一边，按下 % 将光标移动到另一边
Lesson 4.4 替换命令
:s/old/new/g 来将当前行的 &quot;old&quot; 替换成 &quot;new&quot;
g flag 表示将这一行所有的 &quot;old&quot; 替换成 &quot;new&quot;
:#,#s 指定起止行范围
:%s 全文替换
c flag 在替换前进行询问
还有其他 flag
Lesson 5
Lesson 5.1: 执行外部命令
:! 后跟完整命令，然后 &lt;Enter&gt;
Lesson 5.2: 更多有关保存文件的操作
:!ls 列出当前目录所有文件
:w TEST 以 TEST 文件名保存当前编辑内容
:!rm TEST 删除当前目录下的 TEST 文件
Lesson 5.3: 保存选择内容到文件
按下 v 进入 Visual selection 模式
移动光标选择内容
输入 :w FILENAME，底部出现 :&#39;&lt;,&#39;&gt;w FILENAME 类似内容
&lt;Enter&gt;
Lesson 5.4: 读取和合并文件
:r TEST 从文件 TEST 中读取内容写入到光标位置
形似 :r !ls 可以读取外部命令的运行结果
Lesson 6
Lesson 6.1: OPEN 命令
o 在光标下新建一行并转到 Insert 模式
0 在光标上新建
Lesson 6.2: APPEND 命令
a 从光标后插入内容
Lesson 6.3: 替换更多内容
R 进入 Replace 模式，替换更多内容
Lesson 6.4: 复制粘贴内容
v 选择内容
y 复制内容
j$ 跳到下一行行尾
p 粘贴内容
单独的 y 行为类似 yw
Lesson 6.5: SET OPTION
:set ic (Ignore case) 开启忽略大小写
:set noic 关闭忽略大小写
:set invic 切换忽略大小写
Lesson 7
Lesson 7.1: 获取帮助
&lt;HELP&gt;、&lt;F1&gt;、:help 打开帮助窗口
&lt;C-w&gt; 在窗口之间跳转
:q 关闭帮助窗口
:help 后可跟参数
Lesson 7.2: 配置 vimrc 文件
:call mkdir(stdpath(&#39;config&#39;),&#39;p&#39;)
:exe &#39;edit&#39; stdpath(&#39;config&#39;).&#39;/init.vim&#39;
Lesson 7.3: 补全
&lt;C-d&gt; 列出
Tab 补全
进阶
Learn Vim Progressively
Learning Vim in 2013
Vimcasts
Vim Video-Tutorials by Derek Wyatt
Learn Vimscript the Hard Way
7 Habits of Effective Text Editing
vim-galore
看了感觉跟没看一样 (。・_・)/~~~</content>
    <category term="nvim"/>
  </entry>
  <entry>
    <id>https://blog.lnkkerst.me/posts/hello-world-2</id>
    <title type="text">Hello world</title>
    <link href="https://blog.lnkkerst.me/posts/hello-world-2" rel="alternate" type="text/html"/>
    <updated>2022-03-03T15:18:03.000Z</updated>
    <published>2022-03-03T15:18:03.000Z</published>
    <author><name>lnkkerst</name><email>lnkkerst04@gmail.com</email><uri>https://lnkkerst.me</uri></author>
    <content type="text">这是 lnkkerst 的博客的第一篇文章。
已经不知道转生多少次了 XD</content>
  </entry>
  <entry>
    <id>https://blog.lnkkerst.me/posts/hello-world-1</id>
    <title type="text">hello world</title>
    <link href="https://blog.lnkkerst.me/posts/hello-world-1" rel="alternate" type="text/html"/>
    <updated>2019-03-30T05:08:17.000Z</updated>
    <published>2019-03-30T05:08:17.000Z</published>
    <author><name>lnkkerst</name><email>lnkkerst04@gmail.com</email><uri>https://lnkkerst.me</uri></author>
    <content type="text">这是 lnkkerst 的博客中的第一篇文章
#include &lt;cstdio&gt;
int main(){
printf(&quot;hello world!&quot;);
return 0;
}</content>
  </entry>
</feed>
