[{"content":"上次更新甚至是在 3 月写了一个前端的笔记，虽然现在已经不知道多久没有打开 VSC 了码都不会写。按照大部分博客三个月不更新自动删友链的话相比我这本来就没多少的友链还会雪上加霜吧。感谢各位将我留在友链页的各位。\n感觉现在的更新越来越像阿尔吉侬里的近况报告了，从这学期开始开始有了一个记日记的习惯，你会发现记日记这个行为其实其实很可贵，因为人的记忆力意外的不可靠，其实很多时候你当夜记录下的内容第二天起床来看都会觉得很遥远，不是都说要频繁记录自己嘛，虽然断断续续了几天，但是也算是坚持写了一学期的日记了，好像没有什么很明显的变化，但是每天流水账一样记下一些很无聊的事和想法，我觉得可能比做多几个必刷题有意义吧。难得可贵的 17 岁，还是想要尽可能让以后的自己能够回想起来这个还会感动的自己。\n说是高中一年的生活，其实特别恍惚。人的适应能力真的好强大，换做初三的我肯定没办法想象一个能回去听课认真写作业上晚自习、1 个月考 3 次试、坚持做晚练、准时起床睡觉的自己吧，但是就这么挺过来了，好像也没什么，不知道这种麻木感是好事还是坏事，但是这是一种很奇怪的现象，你会感觉到时间过的很快，甚至没有什么记忆的锚点，几天前的事情似乎会变得很遥远，但是一两年前的事情又是那么的清晰和亲切。我发现人如果在很焦虑的时候，就会习惯性把目光放到未来或者过去，我不知道这是不是一种逃避？也许现在的我也处在一种很焦虑的状态吧，但是我自己已经快没有知觉了？我现在还觉得北京的集训好像是上个暑假的事，好像中考完吃的那个铁板牛肉还是昨天吃的饭，但是你要问我上周发生了什么？对不起估计我真的很难回想起来。为什么会这样呢？好奇怪啊。每次进入学校之后就会有一种，被高墙隔起来的感觉，但是已经不会觉得讨厌了，只是觉得感慨，好像我们所有学生熬过这 12 年的高墙生活最后却会发现，高墙之外也没有什么，而且可能走出之后，又见到了新的高墙呢？当新高一和丘进入 202 的时候真的太感慨了，原来去年的我在别人看来是这样的吗，真的好嫩啊，看见年轻的生命力就会会想起自己的过去是这样吗？\n从 OI 脱身之后就失去了评价自己的能力，好像经过了很多的失利之后，就会开始问自己能不能做好哪怕一件事。然后你会和好像抽空了一样，因为有一个支柱一样的东西突然不见了。但是你问我这种感觉是不是不甘心？我想又不是，只是突然觉得很空虚，没有了那种汹涌而来的感觉，要描述的话就是没了心气吗？我想大概是，开始没有办法想一些很远的未来，开始只能关心练习册里斑驳的红笔字迹，开始关心一些鸡皮蒜毛的小事，开始关心前后桌的爱恨情仇八卦趣闻，没有了那种心比天高的感觉，高三能不能考上中大都是问题，中大真的很难考对不起，替过去的我道歉，211 都很难考对不起。其实就是在痛苦或者迷茫的时候人才有时间想一些有的没的，像是读申辩篇、读加缪、读人间失格……高一还是读了一点书的虽然不多。我想找点什么来证明自己的价值，终究无法逃离优绩主义吗。在发现自己确实是一事无成之后就开始劝说自己，“意义不由价值来定义”，然后就更加迷茫了。这学期用尽全力学文化课了，读这么多年书第一次上课听、下课学习、晚自习昨晚全部作业，有史以来第一次期末做完了全部练习册，但是收获了读书以来最差的成绩，因为你发现跟进度就已经没有顾及其他事情的力气了，别说补必修一二的旧知识，于是雪球越滚愈大但是又没有办法，每天都是一个很忙很忙很努力的感觉，但是成绩还是提不上去，均分下一点徘徊，勉强够到一本线，好像每天做的就是写题、看答案、标记红笔、合上、再看一遍，翻下一页。很努力的没用的学习，过了一个学期，什么都没做到，很累。\n烦心的还有家庭和人际关系吧，不想说什么了：\n某日发癫 总之就是很累，你真的要我形容的话，就是有种一块电池一直充不满电的感觉，每天都在透支使用，感觉随时都有可能倒下。最近心脏的问题又有点了但是不敢说，半夜总是会心律不齐惊醒，但是喘不过气的症状倒是没有了，怕是。但是睡眠质量好了不少，睡 6 个多小时也能很有精神了现在，REM 也正常了，虽然还是哪天能睡 7 小时都是奢侈。好像下学期之后我的娱乐活动砍掉了很多？很久没有看番看书弹琴了，每天应付完就精疲力竭，真的是躺下就睡，但是会半夜起来继续失眠，也是挺离谱的。开始练中长跑了，从一点小习惯开始慢慢改变自己吧，健康的身体是最重要的。跑完一个有氧还是挺有成就感的。如果有时间的话，我还是想回到那个能看得下番剧，听得下歌，读得下追忆似水年华的时候。\n高一疯狂迷恋上了 RADWIMPS，每张专辑来回地听，很治愈。现在还开始听华语 Eason 和一点点英语了。换校之后和之前的很多同学断了联系，没有负担的我是不是也有点伪善了？\n起汐恋爱中（存疑）？遇到了一个很好的女孩子，因为关于喜欢和初恋之类的定义容易被浪漫化和曲解就不多说了，我们是完全相反的两个人，磨合起来很麻烦但是很幸福，起汐不是一个喜欢谈恋爱的人，是她诱引我的……但是真的很谢谢她能在我这种时候接住我。我不是擅长写恋爱文字的人，请让我们 skip。\n虽然丧，但是生活还是要继续的，就像暑假还是要继续卷的，自习室应该可以继续更新了，因为小女生是个学霸所以要好好努力，主要是你发现我除了读书之外真的什么都不会了吧，实力跟不上野心，还是想去适应一下做题家的日子，说不定麻木是件好事，希望能早点恢复到应试水平吧。改变一下学习方式，补一下旧知，多做几个题，突然找到以前打 OI 留在主页的一句话，“菜是原罪，有 BB，感叹人生，互吹互膜以及给自己打气的时间不如现在就清楚的意识到自己是个渣渣的本质，然后去刷几道题来提升一下你本来就没多少的水平。”以前觉得能激励自己，现在来看也挺呃呃的。\n现在真的是处于干什么都很没劲的状态，不管是学习还是娱乐。好累啊。\n以前都会在最后放一首歌的，我们来维持这个传统吧。\n嬉しいこと 悲しいことはいつも半分コずつなの\nだからそう 最後はゼロになれるの\n光って消えるただそれだけ信じながら 歌う僕はここにいるよ\n作ってみせるその笑顔も愛しいから もう昨日を探さないでよ\n光って消えるただそれだけと知りながら 光る僕はきれいでしょう?\nだからね 痛む胸に光る種を乗せて 幸せだねって言えるまで\n光ってたいの\n奪って逃げるただそれだけの命なら\n—— RADWIMPS 螢 from RADWIMPS 3 ～無人島に持っていき忘れた一枚～\n看来这世界，似乎还想要驯服我，那就如你所愿吧 我会美丽地挣扎到底~\n明天会是怎么样的一天？\n","date":"2026-07-19T00:00:00Z","permalink":"https://mizusakuraed.github.io/p/2026-07-19-koukou-1st-summer/","title":"高中一年生活随笔"},{"content":"HTML 一般而言，一个初始的 HTML 文件拥有如下结构：\n\u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html lang=\u0026#34;en\u0026#34;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;UTF-8\u0026#34; /\u0026gt; \u0026lt;title\u0026gt;Hello, world!\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;h1\u0026gt;Hello World\u0026lt;/h1\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; 其中：\n\u0026lt;!DOCTYPE html\u0026gt; 作为 文档声明 用于声明当前 HTML 文件的版本，这条语句表示当前使用的 HTML 版本为 5 \u0026lt;html lang=\u0026quot;en\u0026quot;\u0026gt;\u0026lt;/html\u0026gt; 作为 HTML 的根标签，包括了除文档声明之外的所有文件中的 HTML 语句 \u0026lt;head\u0026gt;\u0026lt;/head\u0026gt; 作为 头部，也是当前页面的配置信息，用于外部引入文件 \u0026lt;body\u0026gt;\u0026lt;/body\u0026gt; 作为 内容，用于显示浏览器页面内的内容 注意：\n主流采用 HTML 5 规范 HTML 的文件拥有 .html 和 .htm 两种扩展名 html 标签不区分大小写，在 html 标签中，推荐等号左右不添加空格以增加可读性 HTML 的常用标签有：\n标题：从 \u0026lt;h1\u0026gt;\u0026lt;/h1\u0026gt; 到 \u0026lt;h6\u0026gt;\u0026lt;/h6\u0026gt;，标题字号逐渐减小，标题之间有嵌套关系 段落：\u0026lt;p\u0026gt;\u0026lt;/p\u0026gt; 粗体：\u0026lt;b\u0026gt;\u0026lt;/b\u0026gt;，同时还有易混淆的 \u0026lt;strong\u0026gt;\u0026lt;/strong\u0026gt; 用于强调，其中视障人士的屏幕阅读器会在 \u0026lt;strong\u0026gt; 标签时重读，由此 \u0026lt;b\u0026gt;\u0026lt;/b\u0026gt; 和 \u0026lt;strong\u0026gt;\u0026lt;/strong\u0026gt; 的区别在于一个是为了粗体而粗体，一个是为了强调而粗体 斜体：\u0026lt;i\u0026gt;\u0026lt;/i\u0026gt;，同上有 \u0026lt;em\u0026gt;\u0026lt;/em\u0026gt; 删除线：\u0026lt;s\u0026gt;\u0026lt;/s\u0026gt;，同上有 \u0026lt;del\u0026gt;\u0026lt;/del\u0026gt; 下划线：\u0026lt;hr/\u0026gt; 换行：\u0026lt;br/\u0026gt; 图片标签：\u0026lt;img src=\u0026quot;\u0026quot; width=\u0026quot;\u0026quot; height=\u0026quot;\u0026quot; alt=\u0026quot;\u0026quot; title=\u0026quot;\u0026quot;/\u0026gt; 无序列表：\u0026lt;ul type=\u0026quot;\u0026quot;\u0026gt;\u0026lt;li\u0026gt;\u0026lt;/li\u0026gt;\u0026lt;/ul\u0026gt; type=\u0026quot;circle/square\u0026quot; 表示无序列表前符号使用空心圆还是实心方块 有序列表：\u0026lt;ol start=\u0026quot;\u0026quot; type=\u0026quot;\u0026quot;\u0026gt;\u0026lt;li\u0026gt;\u0026lt;/li\u0026gt;\u0026lt;/ol\u0026gt; start= 表示起始引索，默认为 1 type= 表示有序列表前符号类型： 1 阿拉伯数字 a 小写英文字母 A 大写英文字母 i 小写罗马数字 I 大写罗马数字 超链接： \u0026lt;a href=\u0026quot;\u0026quot; target=\u0026quot;\u0026quot;\u0026gt;...\u0026lt;/a\u0026gt; href 表示地址，target 表示打开方式，在 ... 中写下希望让用户读到的内容 \u0026lt;a href=\u0026quot;#\u0026quot;\u0026gt;\u0026lt;/a\u0026gt; 为假链接，原因是 # 在HTML中表示当前页面的锚点，但如果没有指定具体的锚点 ID，点击后只会回到页面顶部 表格： \u0026lt;table\u0026gt;：表格容器 \u0026lt;tr\u0026gt;：表格行（table row） \u0026lt;th\u0026gt;：表头单元格（table header），默认加粗居中 \u0026lt;td\u0026gt;：标准单元格（table data） \u0026lt;thead\u0026gt;：表头部分 \u0026lt;tbody\u0026gt;：表格主体 \u0026lt;tfoot\u0026gt;：表格页脚 \u0026lt;table\u0026gt; \u0026lt;thead\u0026gt; \u0026lt;tr\u0026gt; \u0026lt;th\u0026gt;表头 1\u0026lt;/th\u0026gt; \u0026lt;th\u0026gt;表头 2\u0026lt;/th\u0026gt; \u0026lt;/tr\u0026gt; \u0026lt;/thead\u0026gt; \u0026lt;tbody\u0026gt; \u0026lt;tr\u0026gt; \u0026lt;td\u0026gt;数据 1\u0026lt;/td\u0026gt; \u0026lt;td\u0026gt;数据 2\u0026lt;/td\u0026gt; \u0026lt;/tr\u0026gt; \u0026lt;/tbody\u0026gt; \u0026lt;/table\u0026gt; HTML 标签的一个难点在于对表单 \u0026lt;form\u0026gt; 的使用。\u0026lt;form\u0026gt; 声明了表单：创建一个表单容器，包含各种输入控件，收集用户输入并通过 HTTP 请求发送到服务器。 格式形如 \u0026lt;form action=\u0026quot;\u0026quot; method=\u0026quot;\u0026quot; target=\u0026quot;\u0026quot;\u0026gt;，其中主要属性有\naction= 用于指定表单提交的 URL method= 表示提交的方式 GET/POST GET：在地址栏后面携带，只能携带字符串，携带的数据大小一般不允许超过 4 KB，缺点是数据暴露、长度限制和编码限制（只能选 URL 编码） POST：在 HTTP 协议的请求体中携带，可以携带任意类型数据，携带数据大小无限制，同时比 GET 更安全，但是 POST 请求不可缓存、不可书签化、多次提交可能重复操作而且性能会比 GET 稍差 target= 在何处打开响应 _self, _blank, _parent, _top enctype= 表示编码类型 autocomplete= 表示是否启用自动填充 novalidate 表示禁用表单验证 常用的表单控件（表单项）有：输入类型 \u0026lt;input\u0026gt;，选择菜单 \u0026lt;select\u0026gt;，文本域 \u0026lt;textarea\u0026gt;：\n\u0026lt;input\u0026gt; 输入框：最常用的表单控件，通过 type 属性可以创建多种不同类型的输入字段 \u0026lt;select\u0026gt; 选择菜单：允许用户从预选项中选择 \u0026lt;textarea\u0026gt; 多行文本域：用于输入多行文本内容，适合长文本的输入 这三者的共同重要特性有：\nname 属性：所有控件都需要 name 属性，用于在提交时标识数据 id 和 \u0026lt;label\u0026gt;：使用 id 与 \u0026lt;label\u0026gt; 关联，提升可访问性和用户体验 required：HTML 5 验证属性，即标记的必填项/必选项 placeholder：输入提示文字 value：控件的默认值或选中状态 还有一些杂七杂八的比如音频、视频、图片标签，还有 \u0026lt;a href=\u0026quot;#top\u0026quot;\u0026gt;Back to Top\u0026lt;/a\u0026gt; 这样的假链接和 \u0026lt;summary\u0026gt;\u0026lt;/summary\u0026gt; 、\u0026lt;details\u0026gt;\u0026lt;/details\u0026gt; 之类的需要时查询即可。 CSS 关于 CSS，首先要引入 HTML 中 div 和 span 的概念：\ndiv 是 HTML 中的一个标签，无特定含义，通常作为自定义的容器配合 CSS 完成网页的基本布局 span 也是没有特定语义的标签，一般作为文本容器出现 两者的区别体现在： div 是“块级元素”，会独占一行；span 是行内元素，不会独占一行 div 可以再嵌套其他标签（因而容易滥用）；span 中只能嵌套文本/图片/超链接 CSS 的基本语法如下： { Property: Value Value; Property: Value Value } 要点在于：\n属性和属性值用 : 连接 如果一个属性有多个值直接用空格隔开 如果有多个属性，属性和属性之间用 ; 隔开，最后一个 ; 可省略也可写 关于 CSS 引入方式的优先级要记住：行内样式优先级永远最高，而内部和外部样式谁写在后面谁优先。 内联（行内）样式通过标签的 style 属性来结合：\n\u0026lt;p style=\u0026#34;Property: Value; Property: Value Value\u0026#34;\u0026gt;\u0026lt;/p\u0026gt; 内部样式通过 style 标签来结合：\n\u0026lt;head\u0026gt; \u0026lt;style type=\u0026#34;text/css\u0026#34;\u0026gt; Selector { property: Value Value; } \u0026lt;/style\u0026gt; \u0026lt;/head\u0026gt; 其中 style 标签必须写在 head 标签的开始和结束标签之间，同时 style 标签中的 type 属性默认即为 text/css 因而可省略不写。 外部样式则为通过 link 标签来结合。\n\u0026lt;head\u0026gt; \u0026lt;link rel=\u0026#34;stylesheet\u0026#34; href=\u0026#34;loc/custom.css\u0026#34; /\u0026gt; \u0026lt;/head\u0026gt; 接下来来看一下 CSS 的基本选择器吧：\n选择器 描述 语法 Eg 标签选择器 根据 HTML 标签名称选择标签 Selector {} div { Property:Value; } ID 选择器 根据 id 属性值选择标签 #id {} #d1 { Property:Value; } 类选择器 根据 class 属性值（类名）选择标签 .class {} .c1 { Property:Value; } 同源选择器 选取所有标签 * {} * { Property:Value; } 此处的优先级大小为：ID \u0026gt; 类 \u0026gt; 标签 \u0026gt; 通用 还有被称为 CSS 组合选择器的：\n选择器 描述 语法 Eg 层级选择器 层级关系选择标签 Parent Son div a{} 属性选择器 根据指定属性的值筛选元素 [Property='Value'] input[type='text'] {} 并集选择器 多个选择器的结果进行合并 Selector1, Selector2, ... .c1, span {} 以下分别为三种 CSS 中常见的属性：背景属性、文本样式和字体属性。\n功能 属性名 属性取值 背景色 background-color 1. 颜色常量\n2. 使用十六进制\n3. RGB 背景图片 background-image url() 平铺方式 background-repeat _ repeat：默认，背景图像将在垂直方向和水平方向重复\n_ repeate-x：背景图像将在水平方向重复\n_ repeate-y：背景图像将在垂直方向重复\n_ no-repeat：背景图像仅显示一次 背景位置 background-position left, top 功能 属性名 属性取值 颜色 color 颜色 设置行高 line-height 像素 文字修饰 text-decoration _ underline：下划线\n_ overline：上划线\n_ ine-through：删除线\n_ none：无线条 文本缩进 text-indent 缩进文本，单位可用 em 文本对齐 text-align 默认值由浏览器决定，有 left, right, center 三种取值 功能 属性名 作用 字体名 font-family 设置字体，需要本机拥有或者在线引入 设置大小 font-size 像素 设置样式 font-style _ normal：默认，标准字体样式\n_ italic：斜体 设置粗细（字重） font-weight 加粗使用 bolder JavaScript JavaScript 能干什么呢？\n操作浏览器（BOM）：网址跳转、历史记录切换、浏览器弹窗 操作网页（DOM）：操作 HTML 标签、标签属性、样式、文本等 注意到 JS 在浏览器内存中进行运行时操作，不修改网页根本源码，刷新网页之后网页还原。\n根据 JS 的作用，不难推断出 JS 的组成：\nECMAScript：JS 的基本语法规范 BOM (Browser Object Model)：浏览器对象模型，与浏览器交互 DOM (Document Object Model)：文档对象模型，操作网页 类似于 CSS，JS 的引入也有在 \u0026lt;script\u0026gt;\u0026lt;/script\u0026gt; 中直接编写和 \u0026lt;script src=\u0026quot;custom.js\u0026quot;\u0026gt;\u0026lt;/script\u0026gt; 引入两种手段。显然，一个 \u0026lt;script\u0026gt; 标签不能同时引入和编写。\nJS 有如下控制台方法：\nconsole.log()：控制台输出正常语句 console.warn()：控制台警告框 console.error()：控制台错误提示 JS 作为一门 弱类型语言，其变量类型由其值决定，定义变量使用关键字 var 或者 let。在作用域、变量提升、重复声明等方面存在显著差异。推荐优先使用 let 和 const，避免使用 var 除非有特殊兼容性需求。常见 JS 变量类型如下：\n数值类型 number，如 1, 2, 3, 3.14 布尔类型 boolean，true, false 字符串类型 string，如 \u0026quot;string\u0026quot;, 'string' 对象类型 object，如 new Date()，null 以及尚未确定的类型 undefined，如 var a 有一函数 typeof() 用于判断变量的类型 对于变量，有运算符 == 比较数值以及 === 比较变量数值和类型。所以会出现经典的： var i = 2; var j = \u0026#34;2\u0026#34;; alert(i == j); // true alert(i === j); //false JS 也有和 C++ 长得几乎相同的 for, if, switch：\n// for for (let i = 1; i \u0026lt;= n; i++) { for (let j = 1; j \u0026lt;= i; j++)、 document.writeln(i + j) } // if var e = 7; if (e == 1) { alert(\u0026#39;1\u0026#39;); } else if (e == 2) { alert(\u0026#39;2\u0026#39;); } else { alert(\u0026#39;7\u0026#39;); } // switch var s = \u0026#34;js\u0026#34;; switch (s) { case \u0026#34;java\u0026#34;: alert(\u0026#34;java\u0026#34;); break; case \u0026#34;javascript\u0026#34;: alert(\u0026#34;javascript\u0026#34;); break; case \u0026#34;js\u0026#34;: alert(\u0026#34;js\u0026#34;); break; } JS 的函数内部有一个 arguments array 用于存放传入的参数，故 函数声明时的参数个数和函数调用时传入的参数个数可以不一致。JS 没有函数重载，同名函数后者覆盖前者。参数列表中直接写参数名而无需写 var。\n// 普通函数 function func(args) { //... return val; } // 匿名函数 function (args) { // ... return val; } 匿名函数的核心应用场景是快速嵌入配合其他函数作用，比如回调函数、事件监听，以及 ES6 中引入的箭头函数，但是注意其无法递归、复用性差。同时 Debug 时在报错栈中会显示为 anonymous 或 ? 难以定位来源。在 JS 中，单独声明一个匿名函数且不将其赋值、传递或立即执行，基本上等于写了一行“废代码”。因而单独的匿名函数声明是无法通过解析的。\nJS 的 事件 指的是发生在 HTML 元素上的“事情”，即浏览器/用户做的某些事情。事件通常与函数配合使用，通过绑定的形式让发生的事件来驱动函数运行。有以下常见事件：\n属性 对应“事件” onclick 当用户点击某个对象时调用的事件句柄 ondblclick 当用户双击某个对象时调用的事件句柄 onchange 域的内容被改变 onblur 元素失焦 onfocus 元素获焦 onload 页面或图像完成加载 onsubmit 确认按钮被点击，表单被提交 onkeydown 某个键盘按键被按下 onkeypress 某个键盘按键被按住 onkeyup 某个键盘按键被松开 onmousedown 鼠标按钮被按下 onmouseup 鼠标按键被松开 onmouseout 鼠标从某元素移开 omouseover 鼠标移到某元素之上 onmousemove 鼠标被移动 如何将事件绑定呢？对于普通/匿名函数各有其方式：\n// 普通函数 \u0026lt;标签 属性=\u0026#34;js 文件, 调用函数\u0026#34;\u0026gt;\u0026lt;/标签\u0026gt;; // 匿名函数 标签对象.事件属性 = function () { // ... }; JS 的数组构建方式如下：\nvar arr = new Array(size); var arr = new Array(elem1, elem2, elem3, ...); // 注意此处上下两种命名方式的设计缺陷：当只有一个参数时语义歧义突变 var arr = [elem1, elem2, elem3, ...]; // 绝对推荐 由 JS 的变量特性我们不难得到：JS 数组中的每个元素都可以是任意类型，JS 数组长度可变，类似于 list。 对于数组 Array 常用的方法有：\nconcat()：连接若干个数组并返回结果 join()：把数组中所有元素放入一个字符串中并通过指定的分隔符进行分隔 reverse()：颠倒数组中元素的顺序 对于二维数组： var arrs = [ [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], ]; for (let i = 0; i \u0026lt; arrs.length(); i++) { for (let j = 0; j \u0026lt; arrs[i].length(); j++) { // ... } } JS 另一个重要的内置对象是 Date 日期：\n创建当前日期 var date = new Date() 创建指定日期 var date = new Date(Y, M, D, H, M, S) 注意月从 0 开始，0 表示 1 月。 日期也有不少自己的 方法。 JS 的 BOM 中封装了浏览器中各个对象，使得开发者可以方便的 操作浏览器中的各个对象。常见的有 windows（窗体对象）、navigator（浏览器导航对象）、screen（屏幕对象）、histroy（历史对象）、location（当前路径信息）。\n方法 作用 alert() 显示带有一段消息和一个确认按钮的警告框 confirm() 显示带有一段消息以及确认按钮和取消按钮的对话框 prompt() 弹出输入框 setInterval(func,time) 按照指定的周期（以毫秒计）来调用函数或计算表达式，请注意是传入函数名 setTimeout(func,time) 在指定的毫秒数后调用函数或计算表达式 clearInterval() 取消由 setInterval() 设置的 Interval()。 clearTimeout() 确认按钮被点击，表单被提交 onkeydown 取消由 setTimeout() 方法设置的 timeout。 方法 作用 appName 返回浏览器的名称 appVersion 返回浏览器的平台和版本信息 方法 作用 width 返回显示器屏幕的分辨率宽度 height 返回显示屏幕的分辨率高度 方法 作用 back() 加载 history 列表中的前一个 URL forword() 加载 history 列表中的下一个 URL go() 加载 history 列表中的某个具体页面 方法 作用 host 设置或返回主机名和当前 URL 的端口号 href 设置或返回完整的 URL port 设置或返回当前 URL 的端口号 JS 的 DOM 用于 访问网页中的所有内容。当网页被加载时，浏览器会创建页面的 DOM 对象。DOM对象模型是一棵树：网页里所有的标签、属性和文本都会被转换成节点对象，按照层级结构组织成 树形结构。其中：\ndocument：整个网页封装成的对象 element：标签封装成的对象 attribute：属性封装成的对象 text：文本封装成的对象 对于标签，获取标签有如下方法： 方法 作用 返回值 document.getElementById(id) 根据 id 获取标签 Element对象 document.getElementsByName(name) 根据元素的 name 属性获取一批标签 Element 类数组 document.getElementsByTagName(tagName) 根据标签名获取一批标签 Element 类数组 document.getElementsByClassName(className) 按根据类名获取一批标签 Element 类数组 接下来看怎么操作标签：\n方法 作用 返回值 document.createElement(tagName) 创建标签 Element对象 parentElement.appendChild(sonElement) 插入标签 element.remove() 删除标签 操作属性：\n方法 作用 返回值 getAttribute(attrName) 获取属性值 属性名称 setAttribute(attrName, attrValue) 设置属性值 属性名称, 属性值 getElementsByTagName(tagName) 根据标签名称获取一批标签 Element 类数组 document.getElementsByClassName(className) 根据类名获取一批标签 Element 类数组 还有操作标签体本身：\n方法 作用 content.innerHTML 获取标签体内容 content.innerHTML = \u0026quot;...\u0026quot; 设置标签体内容 完结撒花，接下来就是学 TypeScript 了 🎉🎉🎉\n","date":"2026-03-07T00:00:00Z","permalink":"https://mizusakuraed.github.io/p/2026-03-07-quick-fronted-dev-learning/","title":"前端三件套速成"},{"content":"咕咕咕鸽了 2 个月终于想起来还有年终总结没有写，前几天去同步云盘上的相册花了好久。。。感觉今年好像干了很多事情啊，去年的年末总结划分了几个大标题最后发现根本整合不起来，今年还得看着照片按时间顺序回顾一下 this 2025。\nOI 终局之战。\n其实如果不是看相册我都忘了今年 1 月我去了铁一，我一直以为是去年的事哈哈。第一次也是最后一次和初中的几个同学出去集训了，当时大家都已经很清楚地感知到自己的上限了，少了竞争对抗，几个同学之间的关系也比以前融洽了许多，有说有笑边颓边学，要说腐也可以颓也可以，但是在铁一的 7 天过得真的很开心，最后的结营赛大家还都打得很好。当时应该写游记的，哦好像写了但是是那几天的做题记录。什么时候打完双人成行啊……到了现在我才能说在 OI 生涯中交到的朋友真的都非常的宝贵。\n快乐 KFC 在 2026 看 2025 的新年礼物 开学之后毫不犹豫选择了停课停课立即停课。停课期间绝对是我学生生涯里最美好的一段时间（之一？）了，今年情况比较特殊，很多人选择不停课，也是政策问题吧，收紧了强基计划之后所有学校的竞赛科都变得保守了，老师也开始不支持，甚至我的教练都总是在让我学文化课。今年整个机房只有我和另一个高一停课，我停 3 个月他停 1 个月 现在人家文化课补完了我还在恶补 不得不说停课的时候思维提升真的大，而且每天模拟 + 练习 + 补题的轮轴转不仅不会累还会感觉每天都过的特别充实，虽然确实说可能我本身还是爱着 OI 的吧 QwQ……包括到了停课期间有时间看看平时注意不到的窗外的景色和蓝天，停下来思考一些文化课里没时间想的人生哲理问题，太美好了。\n如果说今年和去年两次 CSP 都是题目不适应的话，那今年 NOIp 我确实是愿赌服输，考完今年 CSP 之后我是真的在车里哭了一车，仍旧是摔死在能力范围内的简单题，但是最后还是蹭着线去了 NOIp，其实考 NOIp 的时候因为感觉停课期间的训练和准备都很充分所以考场上整个人特别兴奋，当时 20 min 切完 T1 瞅了一眼其他人的屏幕甚至觉得今年自己要进队 AwA，上了个洗手间回来之后就开始坐牢了，是我最不擅长的全计数 NOIp。但是我还是尽力打了 T2 和 T3 我以为很对的一个贪心拼凑，没想到今年 CCF 数据如此给力我直接 T3 全剧终了，按照我当时的 T3 估分那今年我确实是比省一线略高一些过，但是呢，事实如此也没啥说了，赛后很多人都在骂 CCF 的时候我是真的漠然了，愿赌服输，实力不济。下辈子再来。\n欢迎来到 NOIp 2025 说实在话今年整个人状态平复了很多，特别是连续去了人大附中和铁一之后，能很明显感受到正规训练和强校与自己的差距吧，包括人的心态也有所谓成长和变化。到了高中之后也尝试了停课，不得不感慨自己不够努力而且没有更早接触到比较先进的教育资源。但是整个 OI 的圈子的自净程度和资源公开水平是实实在在地提升中的，特别是现在还有梦熊和 LCA 的 trick 公开大战以及像是 ZROI、MXOI 也越来越频繁和传统强校互动承办比赛和集训，让更多非核心地区的学生能够享受到更好的 OI 教育。\n我是绝对绝对不会后悔自己学过 OI 的，我觉得在 OI 的学习中整个人心智的成长和挫折真的成就和塑造了我这个人现在的样子吧。寒假的时候教练问我要不要省选推荐名额，说实话还是犹豫了非常久，最后决定还是放弃了，毕竟我已经没有了最开始那种求胜的热情了，就让这段故事告一段落吧。\n文化课 高中怎么这么难！！！文化课停课之后真的是一落千丈地直下，而且感觉我的理科真是一坨大的，越学越差，也不知道是题做得少还是，也不是不会，就是感觉 trick 一看答案就知道对应哪一个，但是自己写总是写不起来，而且对 math 和 physics 还有一点畏难的心理压力。\n在 OI 之后我一直在找一个能让我继续奋斗下去的精神支柱，在记录贴里有一位神秘访客来到并且写下了 “要不考虑以IIIS为目标试试”这样的留言，很不可思议对吧，在我看来这完全是不可能到达的学府，在接触了北京、广州、深圳的同龄人甚至“孩子”之后深深感受到了自己在这个小地方里的“聪明”其实连人家的起跑线都追不上。我的回复是“尽己所能吧”，这两天休年假有时间停下来思考这个问题，中国有句古话叫做“取其上者得其中”，感觉也确实是这么个道理，包括现在来看如果我当时以的是水个奖就跑路的心态去学 OI 的话想必也不会有现在的这些成长或者说留下来的习惯和思维吧。最近看了一部电影：\n垫底辣妹 ビリギャル 在感慨“大家都是好人”和“好励志啊”之余，老师对 Sayaka 所说的“追逐目标的过程，早已超过了实现目标这件事带来的价值”。\n也许最后还是会一败涂地，也许高考之后读了二流院校，也许将来毕业即失业，也许未来的日子会为了养家糊口而奔波，但是至少希望将来挺着中年大叔的啤酒肚，回味起现在生活的时候，会是“玫瑰色”的吧。我想为了自己的理想而再燃烧一次啊哭哭……\n我要读 IIIS. :)\nACGN + Music 都说 2025 是动画小年，其实这一年因为各种各样的原因（其实本来也没有这种习惯）基本没有追着新番看。接下来就从比较印象深刻的一些的短评里摘抄几句出来吧：\n首先是新番部分：\n意犹未尽的夏天 See you in the summer somewhere. :) 神仙作画，一个讽刺、伤感、温情的地狱 我的夏天还没有结束口牙！一定要去圣地巡礼 能再偷偷我的时间和心脏吗，最后还是唱出来了 我也是原作党哼哼哼。フードコートで、また明日。 然后是补的番啦：实在是太多了就不 Po 了而且每一部都好想要谈谈。\n今年读的轻小说和漫画太多了，中考前基本上是一周过完两到三本连载，现在想起来也是相当惊人：文学少女、妹吻、义妹生活、阶梯岛、Unamed Memory、放学后异世界咖啡厅、关于地球的运动……好多。\n今年也是我正式接触 Gal 这个题材的一年，之前开的 ATRI 和 Aokana 最后都没有推完，今年末上了高中之后倒是突然有了很大的兴趣。\n2025 助力我变为 OTAKU 关注的几只乐队今年的表现都比较的中规中矩，或者说（在我看来）不如以前。这个我们以后有机会开一个系列坑来聊聊。\n产出 把泰罗的摄影系列课算是粗略的看完了，用着家父退下来的 D5100 开始去拍了照片，但是很遗憾是调色都救不回来的烂所以还是 dame，希望今年能在国家地理和 ins 上学到更多吧。我也打算在小红书或者 ins 上发一些自己修完之后认为不错的照片。\n话说为什么我突然找不到自己 THR 的电源线了，导致我今年放假一直没有弹我的吉他，而且好像今年的 guitar time 都被音游抢占了！可怕 😨\n博客现在算是稳定下来了，就用这套 Hugo + Twikoo 的模式，也不太打算大折腾，明年打算开的系列 坑 有：\nMML 读书笔记 前端开发日志？（待定） 高中生活随笔 日音乐队/专辑的前世今生（这个真的很想办，如果有时间的话） 明年再会 明知道不会发生什么，却还是想多等一会儿，想再往前走两步。最戳人的反而是那些看似俗套的东西——夏夜的风、没来得及说完的话、笑得太用力之后突然安静下来的几秒钟——它们像是从你记忆里借来的。看完以后你很难说自己失去了什么，因为你本来也没有真正拥有过。\n讲究的是一个瞬间，人活在一个个瞬间，我们就是这样一种生物啊！\n说不定我们每天度过的日常，是一连串发生的奇迹\n现在我已经不知道回想起一年时感觉时间过得快还是慢表示这一年是充实的，文字功底似乎也咩有什么提升，我还是提笔写不下字，打开键盘没有头绪，争论时异样但无法\n所有的时间都是一期一会啊，下次见面就是明年了，哦不春节完稿的我应该说是今年。希望明年起汐你提笔写下年终总结时能有更多可写和盈满的回忆。\nまた出会うよ~\n","date":"2026-02-17T00:00:00Z","image":"https://mizusakuraed.github.io/post-imgs/2026-02-17-goodbye-2025/hd.jpg","permalink":"https://mizusakuraed.github.io/p/2026-02-17-goodbye-2025/","title":"Goodbye 2025"},{"content":" Companion webpage to the book \u0026ldquo;Mathematics For Machine Learning\u0026rdquo;\n个人学习笔记，欢迎勘误！\n机器学习强调的是设计出来的算法的 “自动”，即机器学习关注的是可应用于许多数据集的通用方法 机器学习的核心有三个概念：数据、模型和学习 机器学习本质上是数据驱动的，因此数据是机器学习的核心 机器学习的目标是设计通用方法，从数据中提取有价值的模式 设计的模型通常与生成数据的过程相关，类似于我们已有的数据集 如果一个模型在考虑了数据之后，在给定任务上的表现有所改善，那么这个模型就可以说是从数据中学习的。 学习可以理解为一种通过优化模型参数来自动发现数据中的模式和结构的学习方法。目标是找到能很好地泛化到我们将来可能会关注的未见数据的好模型 1.1 为直觉寻找词语 机器学习天然分为两个阶段：学习阶段和应用阶段。“机器学习算法”在日常口语和部分文献中被用来指代参与这两个阶段的、功能完全不同的两种系统：\n预测器：一个已经训练好的、可以拿来用的函数或模型。用于应对新的、未见过的数据并返回出预测的结果 训练器：一个自动调整预测器内部参数的过程。通过从大量的训练数据中输出一个优化好的预测器 书中一个有趣的说法是 “模型通常用于描述 生成数据 的过程，与手头的数据集类似。” 模型的核心目的通常是“预测”，这句话中的“生成”，不是指让模型去创造数据，而是指模型试图去模拟和解释“现实世界中的数据（提供的数据集）究竟是如何产生的”。换句话说，“描述生成过程”是模型的“内在本质”，“进行预测”是模型的“外在用途”。好的预测，源于对数据生成过程的良好近似。模型视为黑箱，作为简化的数学结构本质就是一种对数据的生成过程的假设性描述 1.2 阅读本书的两种方法 有很多新鲜的表述，来好好记录解释一下。\n机器学习有如下四大支柱：\n首先是 线性回归。“线性回归的目标是找到将输入 $x \\in \\mathbb{R}^{D}$ 映射到观测函数值 $y \\in \\mathbb{R}$ 的函数”。在这句话中，$x$ 是一个 $D$ 维向量，表示一个数据点；$y$ 是一个实数，表示我们将要预测的标签。我们要找的是一个函数 $f(x)$ 能尽可能准确地预测（对应）$y$，在线性回归中，$f(x)$ 为 $\\theta_0 + \\theta_1 x_1 + \\theta_2 \\times x_2 + \\dots + \\theta_D \\times x_D$ ，我们的任务就是去找参数 $\\theta$。\n线性回归有三种常用的模型拟合方法：\n最大似然估计：假设观测到的数据 $(x, y)$ 是由某个概率模型生成的，比如 $y = f(x) + \\varepsilon$（噪声 $\\varepsilon$ 服从 高斯分布），最大似然估计寻找一组参数 $\\theta$ 使得在当前这组参数下，观测到已有的数据集的概率（即所谓“似然”）最大。这等价于最小化均方误差。\n最大后验估计：在最大似然估计的基础上，我们引入 先验知识。我们不仅考虑数据，还考虑我们对参数 $\\theta$ 可能取值的 先验信念，我将其理解为类似于 prompt，例如参数很可能比较小，模型应该比较简单。最大后验估计寻找在给定数据的前提下，参数 $\\theta$ 本身概率（后验概率）最大的那个值。根据贝叶斯定理，后验概率 $\\propto$ 似然 $\\times$ 先验概率。即我们在最大化似然和先验的乘积。这相当于在最大似然估计的目标函数上加上了 正则化项（L2 正则化，也叫岭规划）。先验知识起到了 防止模型过拟合（参数过大）的作用。如果没有先验，或先验也呈正态分布，最大后验估计将退化为最大似然估计。\n贝叶斯线性回归：不同于前两种“点估计”哲学，贝叶斯线性回归是一种截然不同的方法。贝叶斯线性回归承认不确定性并不对参数做单一的决策。正如 MML 所说，贝叶斯线性回归 “对参数进行积分而不是优化”。前两种方法是“优化”出一个最好的 $\\theta^*$，然后用 $f(x; \\theta^*)$ 做预测。贝叶斯方法是做 “积分”，我们不选择任何一个 $\\theta$，相反，我们计算参数 $\\theta$ 的整个后验概率分布，在这个分布中包含了所有可能的 $\\theta$ 贡献，将其按可信度加权平均。数学上，这个操作就是对参数 $\\theta$ 进行积分：$P(y\u0026rsquo; | x\u0026rsquo;, dat) = \\int P(y\u0026rsquo; | x\u0026rsquo;, \\theta) \\times P(\\theta | dat) d_{0}$。我们得到的不是一个单一的预测值，而是一个 预测分布（通常是一个 概率分布），这个分布不仅告诉我们最可能的预测值（分布的均值），还量化了 预测的不确定性（分布的方差）。这在安全关键或风险评估领域起重要作用。\n从最简单的点估计（MLE）开始奠定基础，加入正则化（MAP）思想提高模型泛化能力，最终上升到完全的贝叶斯视角，拥抱不确定性并得到更丰富的预测信息。\n接下来是降维。回归是 监督学习 这一范式的典范，降维 则是 无监督学习 这一另外范式的经典代表。核心的对比是有标签：\n对于监督学习，比如回归 输入数据形式为成对的 $(x, y)$，$x$ 是输入（特征），$y$ 是与之 明确相关 的标签（输出值）。 算法的核心目标是找到一个函数 $f$，建立从 $x \\to y$ 的映射关系，目标是让 $f(x)$ 能准确预测未来的 $y$ 其本质是学习\u0026quot;因果/关联关系\u0026quot;，我们关心的是 $x$ 如何决定 $y$ 对于无监督学习，比如降维 PCA 输入数据形式只有一对的 $x$，没有对应 的 $y$ 算法的核心目标是理解 $x$ 中本身的内部结构、分布和模式。降维的目的是从 $x \\in \\mathbb{R}^{D}$ 中找到一个紧凑的、低维的表示 $z \\in \\mathbb{R}^{K}$，其中 $K \\lt D$，通常 $K \\lt \\lt D$。 其本质是探索数据内在的规律，我们只关心 $x$ 本身 MML 中描述降维为 \u0026ldquo;为高维数据找到一个紧凑的低维表示\u0026rdquo;。想象一下，PCA（主成分分析）要做的事情是，从一个庞大的拥有极大维度的数据中，找到 几个全新的、自定义的维度，用这几个新的维度来最大程度保留这些极大维度的 主要信息。新的信息指的是原始的极多特征的线性组合，第一主成分是数据分布最分散的方向；第二主成分是与第一主成分正交且剩余方差最大的方向……主成分的紧凑性和易分析性体现在可视化、去冗余和降噪上。\n一个重要的联系是，虽然降维本身是无监督的，但是它的结果即低维特征 $z$ 可以作为监督学习的输入从而提高模型性能，原因是 $z$ 的信息密度更高且减少了冗余与杂声。\n第三个支柱是密度估计，其核心目标是用概率分布描述数据本身的结构，而不是找映射或压缩数据。关键要点在于 “描述给定数据集的概率分布”，我们假设观测到的数据点 $x$ 是从某个未知的概率分布 $p(x)$ 中采样得到的，算法的目标是根据有限的数据样本估计出这个分布 $p(x)$ 的具体形式，换句话说输出一个函数 $f(x)$ 使得输入任意一个数据点 $x$ 就能输出该点对应的概率密度。常用的算法有高斯混合模型（GMM）和 EM 算法（期望最大化算法）。密度估计的应用场景有：异常检测，低概率密度区域的数据点可能是异常值；数据生成，从学到的分布中采样，生成新数据；聚类，GMM的每个成分可以解释为一个聚类（软分配）。\n第四个支柱则是分类，其核心目标是学习从输入 $x$ 到离散标签 $y$ 的映射关系。注意其与回归的区别：\n标签类型：回归为连续整数；分类为离散整数或类别 预测输出：回归为数值；分类为离散标签 任务本质：回归为拟合曲线；分类为寻找决策边界并划分空间 一个新的关键词是支持向量机 SVM，其核心思想是找到一个最优的 决策超平面，使得两个类别之间的 间隔最大 以提高模型泛化能力——离决策边界越远的样本，分类越可靠。支持向量决定了这个最优超平面的关键样本点（通常位于间隔边界上）。\n支柱 问题 输入 典例 输出 回归 $x \\to y$ 的连续映射 有标签 $(x, y), y \\in \\mathbb{R}$ 线性回归 预测函数 降维 数据的高效表示 无标签，只有 $x$ PCA 低维表示 密度估计 数据的概率描述 无标签，只有 $x$ GMM 概率分布 分类 $x \\to y$ 的离散映射 有标签 $(x, y)$，$y$ 属于离散集 SVN 分类器 关于方差 方差是机器学习中无处不在的概念，因为它量化了不确定性和可变性。在模型评估中：偏差-方差权衡。任何模型的误差都可以分解为三部分：\n总误差 = 偏差² + 方差 + 不可约误差 偏差：模型预测的平均值与真实值之间的差距 高偏差：模型过于简单（欠拟合） 用直线拟合抛物线数据 方差：模型对训练数据微小变化的敏感程度 高方差：模型过于复杂（过拟合） 高阶多项式严格穿过每个训练点，但对新数据预测波动大 一些经典的权衡是：\n在简单模型上：高偏差，低方差，稳定但可能不准确 在复杂模型上：低偏差，高方差，准确但不稳定 设计算法的目标就是找到最佳平衡点\n","date":"2026-02-07T00:00:00Z","permalink":"https://mizusakuraed.github.io/p/2026-02-07-mml-c1-notes/","title":"MML C1 阅读笔记"},{"content":" 上高中啦~但是退役啦。\n容易いことではないけれど、答えは別にある。\n如果你在我初中的时候和我说高一 NOIp 之后退役，我估计会，怎么说，受不了。但是谁知道呢，真的到了做出决定的时候居然这么平静是我没想到的，我可能真的不是很适合打 OI 吧。想来我的 OI 生涯真是相当单薄的，没有任何一个拿得出手的奖项，所以也不会有长篇的轰轰烈烈的退役记，可能就是游记里几句话的事吧。\n嗯，这次真不是奔着拿奖去的，我从 OI 中已经学到够多东西了，而且对我来说真的弥足珍贵，这次让自己好好享受一次比赛吧，和这个倾诉了三年的故事告别。\n青春是即使知道结局也不会想要按下的快进键。\n我很开心。虽然天天骂着 OI 害人不浅，但是如果再来一次我还是会选择 OI 吧。\nDay -3 明天中午应该会回家，早上打了一场考前热身赛，不出意外地在每个题上有不同程度的挂分，算是我的特色了。感觉长训下来之后脑子有点转不过来了，无法长时间专注地深度思考，有点担心状态啊，这两天比赛调整一下吧。\n中午午睡了一下，起床之后 秒了一个 *1600。开始做一些 CF 练练思维调整一下\n下午和 @Kotobuki_Tsumugi 一起在弹出韩信听歌，怀旧场，非常感慨啊。下面是发癫实录。\n晚饭鱼丸 + 面饼 = 8 元。\nDay -2 完蛋了，好像中流感了 ，真不能让我体面地离开吗 QAQ。有点头晕，疯狂流鼻涕。\n回家，打洛谷和 QOJ 的板子。\n真感冒了，提前睡觉去。\nDay -1 流感发作了，咳嗽头晕流鼻涕。\n起太早了，到高铁站之后等人，然后登车前往人上人城市深圳。\n高铁上太累了，睡。\n就是小孩子比较烦，办酒店入住办了好久。到了酒店无聊地刷了一下手机，头晕没办法，继续睡了 1 h 左右，起来好多了（实则是教练发身份证吵醒了）。醒了之后和隔壁学校的好同学们 联谊 到我们酒店吃晚饭，隐私照片太多了就不发了。只需要知道有三个引诱痴（@HZH_DCM + @kkvyaivw + @sevenki）刚到酒店房间就开始打某神秘引诱。\n非常好三国杀，使最后一晚旋转。估计再也没有办法这群人一起出来玩了吧。这个名为 svk 的人是真的菜。\n有趣的是夜宵点错了，我们吃了肯德基，神秘 svk 有积分抵消 100RMB 非常牛，使我们 26 元吃 5 人餐；然后又点了披萨、烤鸡和奶茶。不敢点辣的怕明天暴毙。披萨点成了神秘榴莲味，尝试投喂 @mengluosite 失败。\n和 @Kotobuki_Tsumugi 挑了好久最后选择看 国民优选 咒回 0，原因是不需要脑子。可惜的是看到高潮部分被 NIDIE 和 svk 叫走回酒店了，希望明天能看完。\n背一下板子，然后准备睡觉。希望人没事。吃了 3 通药了。\nNOIp！！！ 来了。差点醒不来。这酒店早饭什么东西啊，难吃还没东西，位置还坐满了。随便扒拉两口带上买的宝矿力和巧克力飞奔大巴前往考场。\n比较难绷的是拍照花了至少 10 分钟，好尴尬。\n此处应有一张 NOIp 合照。但是好多人脸不发了。\nNOIp 没什么好说的，简单的 NOI Plus，签完 T1 的签到题之后开始罚做，敲了个暴力和 T3 的一个神秘贪心，感觉 T3 正解是若干贪心拼起来？不确定。毫无区分度的 CCF Like 比赛，符合刻板影响了。不挂分应该能擦着省一线或者下面一点？好像分好挺高？但是无所谓了，没想到手感最好的比赛居然是退役战说是，明明是抱着享受比赛的心态打的反而舒服得多。最后 check 的时候在 #include 前加了 // Goodbye OI（话说这高中园的电脑奇烂无比，卡而且很多废物键盘不灵）。\n出考场一片鬼哭狼嚎。\n回酒店喝了杯果茶 全校最晚登上校车的两人。\n此处应有 kkv 的私人写真照，但是不发怕被 gank。\n高铁上习惯性打开电脑看了一下昨晚打的 CF 准备开始卷，发现已经没有卷的必要了？？？于是爽爽打 PJSK，一周新手初见杀 23，这就是 PJSK 的魅力吗\n突然注意到返程的大巴和高铁上听的分别是 星座になれたら 和 アルジャーノン，居然和我第一次外出打比赛时听的是一样的，也算是有始有终，小小感动了一番。\n终于结束了。也是能给自己打上那个 AFOed 的标签了。\n都结束力！\n一些想说的话 首先是关于“选择”。\n退役绝对是一个对我来说很重要的选择。感觉自己终于能走出这种选择——后悔——内耗的状态了。\n我觉得说来说去还是最老土的“不要美化自己没有走过的那条路”，要有那种怎么说当时很重要的事情现在回头一看都有“回首向来萧瑟处，也无风雨也无晴”的心境，其实我觉得最重要的根本不是“害怕做选择”这件事，我们真正缺失的是相信并坚持自己所选择道路的勇气。\n不用去想“哪个是更好的”“那样说不定能赢”之类的，生活不可能总是玫瑰色万事顺遂的，砸破自己的四叠半，我们能做的就是怀着勇气迈向自己选择的那一种可能性，也许做不到最好但能在自己的这一次选择上回想时得到“啊尽力了没什么遗憾”的感觉，这样才是赚的，不然无法重来的我们在一条路上后悔没有做出另一条道路的选择不是很不划算吗。\n叽里咕噜写了一大堆，体现了 AI 终究无法取代人类。\n我到底从 OI 中学到了什么？如你所见，我没有拿的出手的成绩，除了 CF、AT 和平时过得去的模拟赛成绩，我的正赛日常爆炸，我也对 OI 赛制有了敏感体质。那到底是什么支撑着我、也许是你继续学着 OI 呢？也许是对 whk 的厌恶？也许是对优绩主义当行应试教育体质的反击？我想总归会回到一点──你找不到什么另外的事情就算不赢也能坚持着做下去。这也就是我上面所说的选择。\n很高兴 OI 还没有变为一个可以通过堆砌金钱和知识点的竞赛，也许有这样的趋势但是我对 OI 圈子选手的流动性和自净能力持乐观态度。我们有了一种可以做自己“想要”做的事情的机会。做出这样的选择已经是相当大的进步和眼界的开拓了。比同龄人有了一个自尊为“竞赛生”的身份，多了一些接触当前学龄之外的东西无疑是令人兴奋的。\n其次是对资源的筛选和信息的处理。在 OI 知识难以成体系地手把手传授的情况下，（绝大部分）自学选手的学习途径是互联网上的公开资源加上少许的网课，以及如果学校有提供的模拟赛资源。对这些良莠不齐鱼龙混杂的信息进行加工处理，整理出自己所需要的所能吸收的东西的能力成了家常便饭，但这对大部分同龄人（乃至成年人）来说其实是一种强大的能力。\n关于资源和 OI 思维方式、体制（？）的讨论 lca 的论述比我详细得多，这只是我自己的一点小小见解，不见得就正确。\n最后想说的是 OI 真正对我来说也许影响了一生的东西，其实是在“挫折”中的成长。毫不夸张地说，我无数次后悔为什么要选择 OI，我也还记得和同校的同学竞争集训名额时焦头烂额的时候，也记得 CSP-S 2024 前长达几个月的失眠和焦虑。我们大部分人都是从一个居于高位者来到 OI 这个领域，不知道过了多久才认识到自己其实并没有所谓的天赋和能力。在无数次的质问、迷茫和徘徊之中，一次次选择 once again，当我们决定为了自己的理想而燃烧，其实就是竞赛能带给我们终其一生的财富。所以我们常常看到不少 OI 选手退役回归高中之后并没有同学那么病态的状态。\n请珍惜你在 OI 途上所遇到的每个同学和朋友，每个人都有短板和性格上的残缺，希望你能理解这一点并学会接纳，因为往往 OI 选手的性格和心理问题会更严重一些，也会有不少超脱同龄人圈子的成熟。你的队友或者是同学往往也是你的对手，希望你能正视这份关系并好好维持共同进步下去，相信我这段友谊是非常宝贵的，或许是为数不多长时间会保持联络和交往的知心朋友。详情参见李学“兄弟会”一节\n最后也不知道自己到底想说些什么，能在这里写下这么多东西说明我真的还是对 OI 抱有自己的那份感情吧。你要说没有遗憾是假的，但是我确信自己已经从 OI 中收获到了足够多的重要的受用终生的东西。\n最后我想感谢执教过我的三位教练；感谢和我一起训练了 2 年的那 4 个人；感谢我在 OI 中遇到的每一个老师和选手，谢谢你们。\n很感谢你能看完这篇文章和我的这些碎碎念，如果你是在役的选手，希望你能不留遗憾走完自己的竞赛之旅；如果你是退役或者将退役的选手，希望我们之后都能用更多的方式拓宽自己生命的宽度和厚度。\n过去已经凝固，我带着回忆向前。\n嗯那就是这样，退役快乐。\n言葉は何にもいらないから、夏が終わって往くんだね。\n","date":"2025-11-29T00:00:00Z","permalink":"https://mizusakuraed.github.io/p/2025-11-29-goodbye-oi/","title":"NOIp 2025 游记"},{"content":"不久前补完了春物三季的动画，不得不说后劲真大啊，有蛮多感触的，想在这里写一下。还没有补完原作，不完之后可能还会写点新的进来吧。\n才疏学浅，文笔很烂，见谅。\nHatsu 春物的三季动画看起来会变成 S1 + (S2 + S3) 的感觉，很优秀的一点是情节的过渡使得其观感并不割裂，完成了从“青春校园恋爱喜剧”到“严肃感情剧”的转变。第一季就是很经典的单元剧模式，通过侍奉部的活动来引入情节、人物和设定，比企谷八幡的独特手段可见一斑，伏笔埋得确实不错。从第二季开始连 OP、ED 都变得沉重了，几乎完全抛弃了喜剧元素，转而聚焦于三人团的内心挣扎和关系变化。 不再是解决别人的问题，而是转向解决侍奉部内部的问题。学生会选举、情人节巧克力制作、毕业舞会等事件，都很好地激化了三人矛盾并迫使他们直面“本物”主题。\nS1 是比企谷对于“虚伪”的批判，青春是一场谎言。他认为自己一无所有，通过“自爆”来解决别人的表面和平，本质上这个时候已经开始了他对于“本物”最初步、和扭曲的追求，或者说开始了对于“伪物”的批判——他通过独自揭露和承受虚伪来保护他人之间的真实；S2 是对于“本物”的追求，自爆式的做法埋下的雷全都爆了，在侍奉部的压力下，他终于获得了一个重新审视自己的机会，也喊出了那句经典的台词：“即便如此，我想要的还是真物。” 从单纯地批判伪物，转向了主动追寻一种真实、深刻同时也痛苦的关系。S3 则围绕着如何去定义和实现他们心中尚不明晰的“本物”展开，和雪乃之间从“共依存”的扭曲关系，到最后扭曲的告白“请给我扭曲你人生的权利”正如老师所说的是比企谷自己对于“本物”的一种解答——共同负责和承担、不完美同时扭曲至极，但是却有着全新的“真实”的承诺。\n比企谷的自爆到直面，雪乃的从完美到完整，结衣的从迎合到真诚，三人的转变就是剧情走向的完美体现。\n碍于篇幅与我个人对于雪乃的偏好，我就不在这里对于人物形象进行我的“正论”阐述了。\nZoku 从“伪物”来理解“本物”是轻松的吗？以叶山团体为代表的整个青春世界的常态，那些为了维持表面和谐、避免冲突而构建的、脆弱且虚假的人际关系只不过是舒适但脆弱的虚假。\n但“本物”作为这部作品最为哲学的内核，我很赞同这个东西难以言说传达的观点，不同于毫无矛盾、心意完全相通的理想级状态。正如比企谷所说“什么不说也能够传达，什么都不做也能够理解”的关系，或许只是一种“愚蠢而又美丽的幻想”，也是老师所说的一种逃避。在超越了语言的理解之上，“本物”又囊括了冲突、嫉妒、占有欲……它要求双方共同承认和接纳最真实、最不完美、最丑陋的一面，这也就是在这样一段关系中扭曲、痛苦、挣扎的由来。“本物”需要付出巨大的努力去追求和维持，是一个主动去理解对方，受伤也要继续前进的过程。它绝对是一种沉重的责任，大老师极为中二的表白正意味着承担起干涉、影响雪乃人生的全部责任。\n在作品中的表现就是比企谷与雪乃之间的关系，这最终被定义为一种“共依存”的病态存在。但在这里，这种连结不是一个词就能了断的，而是一种独一无二、他人无法理解的深刻。他们彼此需要，相互支撑，甚至可以说他们的存在定义了对方的一部分。这虽然不健康，不正常，但对他们而言，却是绝对的“本物”，不正确，但确实是一个满分的答案。\n我们更深入地来看看本和伪。\n“伪物”其实不只是虚假和表面，在春物中更是一种维持社会运作的、必要的恶，春物深刻之处在于，它并非简单地将“伪物”判为死刑，而是承认“伪物”是也是交往的必需品，大多数人际关系都建立在一定程度的“伪”之上，每个人都在自觉或不自觉中签署的这份契约。作为生存策略，免去摩擦、降低社交成本，我们发展出阅读空气的做法，这就是构建一个“伪物”的核心。他们并非不知道彼此关系的脆弱，但他们共同维护这个“美丽的世界”，因为脱离这份关系的代价是他们不愿承受的。因此，“伪物”并非简单的谎言，不同于比企谷感性的追求，这而是一种真正理性的、趋利避害的生存选择。\n“伪物”的深刻体现在结衣的“温柔”之上，这种为对方考虑的温柔和体谅迎合了三人关系的需要，她正如阳乃所说是一个最成熟的人，最早学会了同这个世界相处的方式。通过所谓温柔，她剥夺了每个人说“不”的权利，剥夺了冲突的可能，从而也剥夺了通过冲突达成真正理解的机会。正因为结衣陷入与这份温柔的泥潭中，比企谷极端的自爆和反抗才会成为她的救赎——宁愿用丑陋的恶意来打破虚假的温柔，也不愿在其中窒息。\n在伪物的关系中，语言是不可信的。“我们是朋友”可以在这里毫无分量。正因为语言可以被轻易地用来构建和维护“伪物”，比企谷的“不要言语”也是认清了语言在粉饰表面和平上的便利和在表达真实情感上的无力。\n“本物”是一种永远不会到来的状态，它永远在向我们走来，却永远不会停下脚步驻足。对于“本物”的渴求，本质上是我们在伪物世界中对于自我的确认，我们总希望有人能在这个虚伪的人际世界里看到我们最真实、最不堪的内核，并依然选择接纳。这种接纳证明了我们自身的存在与其价值。所以，这不仅仅是想要一个“好朋友”或者“情侣”，而是一种近乎宗教性的、对灵魂伴侣，也就是被调侃的 Soulmate 的祈愿。\n追求本物的过程是没有终点的，哪怕清醒如大老师也难逃在识破人际关系的本质之后的傲慢。平冢静曾一针见血地指出，比企谷追求的“本物”是一个“什么都不用说就能懂我”的关系，这其实是将理解的责任完全推给了对方。他要求对方付出巨大的努力来解读他、包容他，而自己却常常躲起来观察。这是一种极度的自我中心。他渴望“本物”带来的回报，却在很长一段时间里，不知道或者说不愿意去知道如何承担追求“本物”所必须付出的、同等的努力和风险。\n所以他最后迈出与雪乃关系的步伐才弥足珍贵。春物中对于“本物”的最终解答是一种互相伤害的权利。大老师的告白不是“应该还有别的说的吧”那种传统的浪漫情话，“请给我扭曲你人生的权力”完整地承认了两人之间的关系就是共依存或者说互相的依赖和干涉，只要两人的联系依旧存在，就必然影响、改变乃至扭曲其人生；同时有彻底的坦诚与脆弱，主动放弃对你的设防，我允许你进入我的内心，对我施加影响，即使这会带来痛苦；最浪漫的在于共同承担这段关系带来的一切后果，无论好坏。他们之间的关系不再是“互相理解”，而是“即使无法完全理解，也愿意继续尝试理解”。他们选择了带着伤痕和遗憾，一起走向未来。这就是他们对于“本物”的解答。这种外界的“共依存”对他们而言正是通过无数次试探、伤害和挣扎后，唯一能够建立起来的、绝对真实的联结。\nKan 春物的谨慎或者说深刻在于没有将任何状态神圣化。本物是一种理想化的追求，现实中的关系总是在“真”与“伪”之间摇摆，重要的是保持追求真实的勇气。“伪物”是社会常态，你无法逃避。但你可以选择，在你生命中最重要的、独一无二的关系里，是否愿意放弃“伪物”带来的安逸，面对自己的自私、傲慢、痛苦，甚至可能是错误，去承受追求“本物”所带来的一切痛苦、责任与不确定。\n正如老师所说，真正的温柔不是无人受伤，对于重要的人就是会不停的痛苦和挣扎。温柔是有勇气与重要的人一起承受伤害，并携手走下去。真正的“强大”不是永远正确、永不依赖，而是敢于承认自己的软弱，并依然选择前行。也许我们终其一生无法找到像大老师和雪乃之间那样的联系，但做出追求本物这个抉择，在充满了误解、伤害和痛苦的过程所抵达的那个不完美、有些扭曲、却无比坚实的终点，正是我们青春乃至人生中最宝贵的财富。\n看完之后确实震惊了很久，很久没有这种一口气追着时间赶紧看完的体验了。Feel 社的文戏改的确实不太好，而且偏爱团子让我一直找不到雪乃戏份相当难受 :(，但是制作的提升是实打实的，听说原作中对于雪乃独白的描写非常的出彩，过两天开始补一下。\n我觉得渡航是狡猾的，他直到结束都没有阐明自己对于“本物”的理解，而是将这样一个个问题甩锅给我们每一个读者：我们是否沉浸在温柔的伪物之中？是否忘记了自己对于本物的追求？我们所渴望的本物究竟是什么？但他也是温柔的，一个永远不会完结的青春物语，一个难以得到解答的青春问题，也许是他对于自己也是读者的青春所留下的延音，只要我们依旧疑惑着、痛苦着、追寻着，我们就还存在于这个“充满谎言”的青春当中。\n也许若干年后，也许真的到了 2041 年，当我们重新审视自己曾经写下的这些稚嫩的文字，也会像大老师一样发出「やはり俺の青春ラブコメはまちがっている。」的感慨吧，而我期待着那一天的到来。\nKan ","date":"2025-11-29T00:00:00Z","permalink":"https://mizusakuraed.github.io/p/2025-09-23-oregaku/","title":"Oregaku——关于春物的杂谈"},{"content":"何为树链剖分 树作为一种性质丰富的图，在 OI 中有非常广泛的命题空间。我们有这不少对树上操作的手段，但是并没有一种直接的数据结构可以处理树上的信息。树链剖分通过通过一种特殊的链剖分技巧，将对树上任意一条路径的操作转化为对数段序列上的操作，对于序列，我们就有线段树、树状数组等数据结构来处理了。\n来看一个经典问题：给定一棵 $n$ 个节点的树，节点带权值，需要支持两种操作：\n修改 $u$ 到 $v$ 的路径上所有节点的权值 查询 $u$ 到 $v$ 的路径上所有节点的权值和 如果这棵树是一条链，那直接可以丢到序列上来维护了，但很可惜这棵树的形态任意。我们可以用暴力的手段：找到 $lca(u, v)$，分别从 $u, v$ 向上走，复杂度是 $O(n)$ 的。\n为了处理这种问题，树链剖分应运而生。通俗的说，树链剖分的思想是 化树为链，将树上任意的路径问题转化为序列上的区间问题。\n树链剖分怎么做 我们常说的树剖，指的是重链剖分，在开始实现树剖之前我们首先引入几个概念：\n重儿子：对于任意一个非叶子节点，其子节点中子树最大（子树结点最多）的儿子。若有多个，任取其一皆可；若没有子节点，则无重儿子 轻儿子：一个节点除重儿子之外的子节点 重边：连接一个节点与其重儿子的边 轻边：连接一个节点与其轻儿子的边 重链：由若干条首尾相接的重边连接而成的路径。特别地，若从一个轻儿子节点出发，则这个轻儿子也算一条重边的起点 偷一张 OI-Wiki 被刨到包浆的图：\n补充：落单的节点自身视为一条重链。\n通过这些定义，我们可以将树中所有的节点划分到唯一的重链中。\n树剖的实现依赖于两个 DFS 和后续的数据结构维护，其中第一个 DFS 处理出每个节点的 父节点、深度、子树大小和重儿子。OI-Wiki 中的 void dfs1(int u) 会导致 dfs2 时 stack-overflow，避坑。\n// fa(u): u 的父亲；dep(u): u 在树上的深度；siz(u): u 的子树的节点个数；son(u): 表示节点 u 的重儿子 void dfs1(int u) { son[u] = -1, siz[u] = 1; for (auto v : G[u]) { if (v == fa[u]) continue; fa[v] = u; dep[v] = dep[u] + 1; dfs1(v); siz[u] += siz[v]; if (son[u] == -1 || siz[v] \u0026gt; siz[son[u]]) son[u] = v; } } 第二个 DFS 处理出 每个节点所在重链的顶点，以及每个节点的 DFS 序。注意在遍历时需要优先遍历重儿子，保证同一重链上的节点的 DFS 序是连续的。\n// top(u): u 所在重链的顶部那个深度最小的节点；dfn(u): u 的 DFS 序，即在线段树中的编号；rnk(u): DFS 序所对应的节点编号，rnk(dfn(u)) = u void dfs2(int u, int t) { top[u] = t; tot++; dfn[u] = tot; rnk[tot] = u; if (son[u] == -1) return; dfs(son[u], t); // 重儿子优先 for (auto v : G[u]) { if (v != son[u] \u0026amp;\u0026amp; v != fa[u]) dfs2(v, v); } } 操作树剖结果 回到我们最初提出的问题，对于路径 $(u, v)$ 的修改和查询，我们可以利用处理出的 $top$ 像倍增 LCA 过程一样向上跳。对于路径 $(u, v)$：\n选择 $u, v$ 中 $top$ 不相同且深度较深的节点，比如 $u$ $u$ 所在的重链 $(top(u), \\dots, u)$。由于这条链上的 $dfn$ 是连续的，所以在线段树上直接操作 $[dfn(top(u)), dfn(u)]$ 整个区间 之后将 $u$ 跳到 $fa(top(u))$，这样子 $u$ 就跳出了原本所在的重链而来到链顶的父亲节点 重复这个过程，直到 $u, v$ 处在同一条重链上，此时 $top(u) = top(v)$ 在同一条链上的 $u, v$ 之间的路径也对应 $dfn$ 中的一个连续区间 $[dfn(u), dfn(v)]$，再平推一次线段树的操作 如果是对于整个子树进行操作，由于 $dfn$ 的定义，不难得到所有节点的 $dfn$ 恰好构成一个连续的区间 $[dfn(u), dfn(u) + siz(u) - 1]$，因此也可以转换成一次线段树的区间操作。\n补充一下树剖的额外用法：求 LCA。不断向上跳重链，当跳到同一条重链上时，深度较小的节点即为 LCA。向上跳重链时首先要先跳重链顶端深度较大的一个。\nint lca(int u, int v) { while (top[u] != top[v]) { if (dep[top[u]] \u0026gt; dep[top[v]]) u = fa[top[u]]; else v = fa[top[v]]; } return (dep[u] \u0026gt; dep[v] ? v : u); } 练题 树剖离不开练。\nLG P3384 【模板】重链剖分/树链剖分 年轻人的第一份树剖代码，裸的代码实现一下上面的需求罢了。\n#include \u0026lt;bits/stdc++.h\u0026gt; #define int long long constexpr int N = 1e5 + 7; int n, m, r, P; int tot; int w[N]; int fa[N], dep[N], siz[N], son[N]; int top[N], dfn[N], rnk[N]; std::vector\u0026lt;int\u0026gt; G[N]; struct SegTree { struct node { int val, add; } tr[N \u0026lt;\u0026lt; 2]; #define ls(o) (o \u0026lt;\u0026lt; 1) #define rs(o) (o \u0026lt;\u0026lt; 1 | 1) void maketag(int o, int l, int r, int v) { tr[o].add = (tr[o].add + v) % P; tr[o].val = (tr[o].val + (r - l + 1) * v) % P; } void pushup(int o) { tr[o].val = (tr[ls(o)].val + tr[rs(o)].val) % P; } void pushdown(int o, int l, int r) { int mid = (l + r) \u0026gt;\u0026gt; 1; maketag(ls(o), l, mid, tr[o].add); maketag(rs(o), mid + 1, r, tr[o].add); tr[o].add = 0; } void build(int o, int l, int r) { if (l == r) { tr[o] = {w[rnk[l]], 0}; return; } int mid = (l + r) \u0026gt;\u0026gt; 1; build(ls(o), l, mid); build(rs(o), mid + 1, r); pushup(o); } void update(int o, int l, int r, int ql, int qr, int v) { if (ql \u0026lt;= l \u0026amp;\u0026amp; r \u0026lt;= qr) { maketag(o, l, r, v); return; } int mid = (l + r) \u0026gt;\u0026gt; 1; pushdown(o, l, r); if (ql \u0026lt;= mid) update(ls(o), l, mid, ql, qr, v); if (qr \u0026gt; mid) update(rs(o), mid + 1, r, ql, qr, v); pushup(o); } int query(int o, int l, int r, int ql, int qr) { if (ql \u0026lt;= l \u0026amp;\u0026amp; r \u0026lt;= qr) return tr[o].val % P; int mid = (l + r) \u0026gt;\u0026gt; 1, res = 0; pushdown(o, l, r); if (ql \u0026lt;= mid) res = (res + query(ls(o), l, mid, ql, qr)) % P; if (qr \u0026gt; mid) res = (res + query(rs(o), mid + 1, r, ql, qr)) % P; return res % P; } } seg; void dfs1(int u) { son[u] = -1, siz[u] = 1; for (auto v : G[u]) { if (v == fa[u]) continue; fa[v] = u; dep[v] = dep[u] + 1; dfs1(v); siz[u] += siz[v]; if (son[u] == -1 || siz[v] \u0026gt; siz[son[u]]) son[u] = v; } } void dfs2(int u, int t) { tot++; top[u] = t, dfn[u] = tot, rnk[tot] = u; if (son[u] == -1) return; dfs2(son[u], t); for (auto v : G[u]) { if (v != son[u] \u0026amp;\u0026amp; v != fa[u]) dfs2(v, v); } } void solve1(int x, int y, int z) { while (top[x] != top[y]) { if (dep[top[x]] \u0026lt; dep[top[y]]) std::swap(x, y); seg.update(1, 1, n, dfn[top[x]], dfn[x], z); x = fa[top[x]]; } if (dep[x] \u0026gt; dep[y]) std::swap(x, y); seg.update(1, 1, n, dfn[x], dfn[y], z); } int solve2(int x, int y) { int res = 0; while (top[x] != top[y]) { if (dep[top[x]] \u0026lt; dep[top[y]]) std::swap(x, y); res = (res + seg.query(1, 1, n, dfn[top[x]], dfn[x])) % P; x = fa[top[x]]; } if (dep[x] \u0026gt; dep[y]) std::swap(x, y); res = (res + seg.query(1, 1, n, dfn[x], dfn[y])) % P; return res; } void solve3(int x, int z) { seg.update(1, 1, n, dfn[x], dfn[x] + siz[x] - 1, z); } int solve4(int x) { return seg.query(1, 1, n, dfn[x], dfn[x] + siz[x] - 1); } signed main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cin \u0026gt;\u0026gt; n \u0026gt;\u0026gt; m \u0026gt;\u0026gt; r \u0026gt;\u0026gt; P; for (int i = 1; i \u0026lt;= n; i++) { std::cin \u0026gt;\u0026gt; w[i]; } for (int i = 1, x, y; i \u0026lt; n; i++) { std::cin \u0026gt;\u0026gt; x \u0026gt;\u0026gt; y; G[x].push_back(y); G[y].push_back(x); } dfs1(r); dfs2(r, r); seg.build(1, 1, n); for (int i = 1, t, x, y, z; i \u0026lt;= m; i++) { std::cin \u0026gt;\u0026gt; t; if (t == 1) { std::cin \u0026gt;\u0026gt; x \u0026gt;\u0026gt; y \u0026gt;\u0026gt; z; solve1(x, y, z); } if (t == 2) { std::cin \u0026gt;\u0026gt; x \u0026gt;\u0026gt; y; std::cout \u0026lt;\u0026lt; solve2(x, y) \u0026lt;\u0026lt; \u0026#34;\\n\u0026#34;; } if (t == 3) { std::cin \u0026gt;\u0026gt; x \u0026gt;\u0026gt; z; solve3(x, z); } if (t == 4) { std::cin \u0026gt;\u0026gt; x; std::cout \u0026lt;\u0026lt; solve4(x) \u0026lt;\u0026lt; \u0026#34;\\n\u0026#34;; } } return 0; } CF343D Water Tree 模板题，但是注意这个线段树的 lazy_tag 初始，因为打的标记就是 $0/1$，所以起始建树为 $-1$。还是不够熟练，记得在线段树上修改要用 $dfn(u)$，两次操作非常简单，没什么好说的。\n#include \u0026lt;bits/stdc++.h\u0026gt; using i64 = long long; constexpr int N = 5e5 + 7; int n, q; int tot; int fa[N], dep[N], siz[N], son[N]; int top[N], dfn[N], rnk[N]; std::vector\u0026lt;int\u0026gt; G[N]; struct SegTree { struct node { int val, lzy; } tr[N \u0026lt;\u0026lt; 2]; #define ls(o) (o \u0026lt;\u0026lt; 1) #define rs(o) (o \u0026lt;\u0026lt; 1 | 1) void build(int o, int l, int r) { if (l == r) { tr[o] = {0, -1}; return; } int mid = (l + r) \u0026gt;\u0026gt; 1; build(ls(o), l, mid); build(rs(o), mid + 1, r); } void pushdown(int o) { if (tr[o].lzy != -1) { tr[ls(o)] = {tr[o].lzy, tr[o].lzy}; tr[rs(o)] = {tr[o].lzy, tr[o].lzy}; tr[o].lzy = -1; } } void update(int o, int l, int r, int ql, int qr, int v) { if (ql \u0026lt;= l \u0026amp;\u0026amp; r \u0026lt;= qr) { tr[o] = {v, v}; return; } int mid = (l + r) \u0026gt;\u0026gt; 1; pushdown(o); if (ql \u0026lt;= mid) update(ls(o), l, mid, ql, qr, v); if (qr \u0026gt; mid) update(rs(o), mid + 1, r, ql, qr, v); } int query(int o, int l, int r, int x) { if (l == r) return tr[o].val; pushdown(o); int mid = (l + r) \u0026gt;\u0026gt; 1; if (x \u0026lt;= mid) return query(ls(o), l, mid, x); else return query(rs(o), mid + 1, r, x); } } seg; void dfs1(int u) { son[u] = -1, siz[u] = 1; for (auto v : G[u]) { if (v == fa[u]) continue; fa[v] = u; dep[v] = dep[u] + 1; dfs1(v); siz[u] += siz[v]; if (son[u] == -1 || siz[v] \u0026gt; siz[son[u]]) son[u] = v; } } void dfs2(int u, int t) { tot++; top[u] = t, dfn[u] = tot, rnk[tot] = u; if (son[u] == -1) return; dfs2(son[u], t); for (auto v : G[u]) { if (v != son[u] \u0026amp;\u0026amp; v != fa[u]) dfs2(v, v); } } void solve1(int x) { seg.update(1, 1, n, dfn[x], dfn[x] + siz[x] - 1, 1); } void solve2(int x) { while (x) { seg.update(1, 1, n, dfn[top[x]], dfn[x], 0); x = fa[top[x]]; } } int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cin \u0026gt;\u0026gt; n; for (int i = 1, u, v; i \u0026lt; n; i++) { std::cin \u0026gt;\u0026gt; u \u0026gt;\u0026gt; v; G[u].push_back(v); G[v].push_back(u); } dfs1(1); dfs2(1, 1); seg.build(1, 1, n); std::cin \u0026gt;\u0026gt; q; for (int i = 1, c, v; i \u0026lt;= q; i++) { std::cin \u0026gt;\u0026gt; c \u0026gt;\u0026gt; v; if (c == 1) { solve1(v); } if (c == 2) { solve2(v); } if (c == 3) { std::cout \u0026lt;\u0026lt; seg.query(1, 1, n, dfn[v]) \u0026lt;\u0026lt; \u0026#34;\\n\u0026#34;; } } return 0; } LG P2590 [ZJOI2008] 树的统计 \u0026amp; LG P3178 [HAOI2015] 树上操作 简单题，比模板还简单。\nLG P4114 Qtree1 原题来自 SPOJ，边权转点权，注意到在树上一个点只与其父亲有且仅有一条边相连，考虑把一条边的权值丢到其一条边的儿子节点上。对于根，由于没有相连的父亲节点边，所以在查询 $sum$ 时将点权设为 $0$；在查询 $\\min/\\max$ 时将点权设为 $inf, -inf$ 即可。同时注意到在修改和查询的过程中不能碰到节点的 $LCA$，所以在处理的最后其区间范围应为 $[dfn(u + 1), dfn(v)]$。\n边权转点权的代码操作主要在 void dfs(int u, int pa, int k) 和建树后的 for 循环里。\n#include \u0026lt;bits/stdc++.h\u0026gt; #define int long long constexpr int N = 3e5 + 7; constexpr int inf = 1e9; int n, ncnt; std::string s; int w[N]; int fa[N], dep[N], siz[N], son[N]; int top[N], dfn[N], rnk[N]; std::vector\u0026lt;std::pair\u0026lt;int, int\u0026gt;\u0026gt; G[N]; struct edge { int u, v, w, x; } E[N \u0026lt;\u0026lt; 1]; struct SegTree { struct node { int val, mxn; } tr[N \u0026lt;\u0026lt; 2]; #define ls(o) (o \u0026lt;\u0026lt; 1) #define rs(o) (o \u0026lt;\u0026lt; 1 | 1) void pushup(int o) { tr[o].mxn = std::max(tr[ls(o)].mxn, tr[rs(o)].mxn); } void build(int o, int l, int r) { if (l == r) { tr[o] = {w[rnk[l]], w[rnk[l]]}; return; } int mid = (l + r) \u0026gt;\u0026gt; 1; build(ls(o), l, mid); build(rs(o), mid + 1, r); pushup(o); } void update(int o, int l, int r, int p, int v) { if (l == r) { tr[o] = {v, v}; return; } int mid = (l + r) \u0026gt;\u0026gt; 1; if (p \u0026lt;= mid) update(ls(o), l, mid, p, v); else update(rs(o), mid + 1, r, p, v); pushup(o); } int query(int o, int l, int r, int ql, int qr) { if (ql \u0026lt;= l \u0026amp;\u0026amp; r \u0026lt;= qr) return tr[o].mxn; int mid = (l + r) \u0026gt;\u0026gt; 1, res = -inf; if (ql \u0026lt;= mid) res = std::max(res, query(ls(o), l, mid, ql, qr)); if (qr \u0026gt; mid) res = std::max(res, query(rs(o), mid + 1, r, ql, qr)); return res; } } seg; void dfs0(int u, int pa, int k) { w[u] = k; for (auto i : G[u]) { auto [v, w] = i; if (v == pa) continue; dfs0(v, u, w); } } void dfs1(int u) { son[u] = -1, siz[u] = 1; for (auto i : G[u]) { auto [v, w] = i; if (v == fa[u]) continue; fa[v] = u; dep[v] = dep[u] + 1; dfs1(v); siz[u] += siz[v]; if (son[u] == -1 || siz[v] \u0026gt; siz[son[u]]) son[u] = v; } } void dfs2(int u, int t) { ncnt++; top[u] = t, dfn[u] = ncnt, rnk[ncnt] = u; if (son[u] == -1) return; dfs2(son[u], t); for (auto i : G[u]) { auto [v, w] = i; if (v != son[u] \u0026amp;\u0026amp; v != fa[u]) dfs2(v, v); } } int solve(int x, int y) { int res = -inf; while (top[x] != top[y]) { if (dep[top[x]] \u0026lt; dep[top[y]]) std::swap(x, y); res = std::max(res, seg.query(1, 1, n, dfn[top[x]], dfn[x])); x = fa[top[x]]; } if (dep[x] \u0026gt; dep[y]) std::swap(x, y); res = std::max(res, seg.query(1, 1, n, dfn[x] + 1, dfn[y])); return res; } signed main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cin \u0026gt;\u0026gt; n; for (int i = 1; i \u0026lt; n; i++) { std::cin \u0026gt;\u0026gt; E[i].u \u0026gt;\u0026gt; E[i].v \u0026gt;\u0026gt; E[i].w; G[E[i].u].push_back({E[i].v, E[i].w}); G[E[i].v].push_back({E[i].u, E[i].w}); } dfs0(1, 0, -inf); dfs1(1); dfs2(1, 1); seg.build(1, 1, n); for (int i = 1; i \u0026lt; n; i++) { if (fa[E[i].u] == E[i].v) E[i].x = E[i].u; else E[i].x = E[i].v; } while (std::cin \u0026gt;\u0026gt; s) { int a, b; if (s == \u0026#34;DONE\u0026#34;) break; if (s == \u0026#34;CHANGE\u0026#34;) { std::cin \u0026gt;\u0026gt; a \u0026gt;\u0026gt; b; seg.update(1, 1, n, dfn[E[a].x], b); } if (s == \u0026#34;QUERY\u0026#34;) { std::cin \u0026gt;\u0026gt; a \u0026gt;\u0026gt; b; if (a == b) std::cout \u0026lt;\u0026lt; \u0026#34;0\\n\u0026#34;; else std::cout \u0026lt;\u0026lt; solve(a, b) \u0026lt;\u0026lt; \u0026#34;\\n\u0026#34;; } } return 0; } ","date":"2025-08-10T00:00:00Z","permalink":"https://mizusakuraed.github.io/p/2025-08-10-oi-hld/","title":"树链剖分笔记"},{"content":"这次我们不谈技巧，尝试来理解一下那些怎么都学不会的线代概念。\n根据 2025 年的 NOI 大纲，线性代数作为 OI 中的考点分散在提高和 NOI 级中，其中有：\n向量与矩阵 矩阵初等变换 矩阵运算及高斯消元 逆矩阵 行列式 向量空间、线性相关 基与线性基 前三者为提高考点，后四者为 NOI 级考点。线性代数相关内容常常作为优化性能或者突破口而出现，如优化递推和线性基在位运算相关题目的运用。我属于那种学了又忘忘了又学每次都好像学会回头就忘的类型，这次把这几个考点串起来写一篇长文，照着 OI Wiki 来写注解和笔记。\n在开篇之前感谢 3B1B 系列视频让笔者醍醐灌顶，还有机械工业出版社的《线性代数及其应用》一书，两者都同时囊括了生动和深度，非常值得一看。\n建议 3B1B 配合关闭弹幕食用，你会在弹幕上发现民科、哲学家、玄学家、一学就会天才大学霸，极大概率只会看到一堆感叹和争吵而没有什么真正有效的信息，事实上大部分的勘误都在视频中指出，并且 3B1B 的视频虽然直观而且短但是信息量极大，经常需要反复观看暂停思考，绝对不是一眼就懂之后啥都没有。当一项事物或概念简单地呈现在面前时，其背后往往有着更为深刻的思想。扯的有点远……看的时候确实看弹幕和评论不太舒适。 向量 $\\text{vector}$ 的定义根据学科的不同而有很大的差异，学习过高中物理的同学也都知道，在物理学中有“标量”和“矢量”之称，在 OI 中，由于偏向于 CS 的属性，我们统一将其命名为“向量”，记为 $\\vec{v}, \\boldsymbol{v}$。\n向量作为线性代数中最为基础的部分，在线性代数中通过研究其加法和乘法来探索和思考，向量是一种既有大小又有方向的量，我们同时也可以将其视为一种特定的运动，类似于在数轴上平移，我们在坐标系内以原点为起点画一条有向的线段，例如对于向量 $\\begin{bmatrix} 3 \\\\ 2 \\end{bmatrix}$，在几何意义上\n向量示意 就是这样一条从原点开始，沿着 $x$ 轴正方向移动 $3$ 个单位，并沿着 $y$ 轴正方向移动 $2$ 个单位的有向线段。这里有几个概念：\n向量的模：有向线段 $\\vec{u}$ 的长度称为向量的模，即该向量的大小，记作 $|\\vec{u}|$ 单位向量：模为 $1$ 的向量称为该方向上的单位向量，记作 $\\vec{e}$ 在编写代码中，向量 $\\text{vector}$ 实际上就是一种 $\\text{array}$：有序的数字列表。类比数的运算，向量加法就是把对应的项相加，或者我们换一种角度，从物理学中的位移概念来看，对于一个人经过的位移 $\\overrightarrow{AB} + \\overrightarrow{BC}$，我们可以将其看为 $\\overrightarrow{AC}$。\n位移拆解 线性组合和向量空间 Easy version 有一个重要的观点是：向量的加法和乘法可以看成向量的缩放和相加。据此，我们重新审视点坐标的表示：\n暂不考虑向量空间和基的严谨表述，我们定义如下图的 $\\hat{i}, \\hat{j}$ 为坐标系的基向量。\n坐标系中基向量 当我们将坐标视为标量，实际上任意的标量都是基向量缩放相加相加处理得来的，当我们用数字描述向量时，事实上就依赖于我们的基。不难发现选取不同的基对于“同一位置”的向量有着不同的表示。\n$$ a \\vec{u} + b \\vec{v} = \\vec{w}, a, b \\in \\mathbb{R} $$\n这种操作称之为“线性组合”，而这个由所有 $\\vec{w}$ 构成的全集，即对于所有可以表示为给定向量线性组合的集合，称之为线性空间、向量空间，更准确地说是向量子空间，如果你看过 3B1B 的视频，译者巧妙地将这个 span 翻译成了“给定向量张成的空间”，非常形象生动。\n对于二维向量的向量空间显然有 3 种情况：点、共线、平面。\n为了便于研究，在研究单个向量时我们将其视作一条箭头，在有多个向量时，我们则简单地将其视为点，因为正如我们上面所说，在研究时我们将其起点视为原点 $(0, 0)$。\n在三维空间的角度下，两个向量的缩放怎样呢？显然我们沿着缩放后的终点绘图可以得到一个过原点的平面，此时我们再施加第三个向量并对其进行缩放，形象地思考，这等同于将前两个向量张开的平面沿着新向量的方向来回移动，从而得到整个空间。\n对于若干个向量，如果我们可以通过移除其中的一个向量而不减少向量张成的空间，我们称它们为“线性相关”的向量。这等价于一个向量可以表述为其他向量的线性组合，因为这个向量落在其他向量张开的空间里，无法形成新的约束。\n若这若干个向量都给向量空间增加了新的维度，则它们是“线性无关”的。\n更进一步的 Hard version 来看看严谨的定义如何吧。\n一个向量空间是由一些被称为向量的对象构成的非空集合 $V$，在这个集合上定义了两个运算，称之为加法和标量乘法（标量属于全体实数），对于 $V$ 中所有向量 $u, v, w$ 及所有的标量 $c, d$ 都要服从以下公理：\n$\\vec{u} + \\vec{v} \\in V$ $\\vec{u} + \\vec{v} = \\vec{v} + \\vec{u}$ $(\\vec{u} + \\vec{v}) + \\vec{w} = \\vec{u} + (\\vec{v} + \\vec{w})$ $V$ 中存在一个零向量 $0$ 使得 $\\vec{u} + 0 = \\vec{u}$ 对 $V$ 中每个向量 $\\vec{u}$，存在一个向量 $-\\vec{u}$ 使得 $\\vec{u} + (-\\vec{u}) = 0$ $c \\vec{u} \\in {V}$ $c(\\vec{u} + \\vec{v}) = c\\vec{u} + c\\vec{v}$ $(c + d)\\vec{u} = c\\vec{u} + d\\vec{v}$ $c(d\\vec{u}) = c(d\\vec{u})$ $1\\vec{u} = \\vec{u}$ 称向量空间 $V$ 的一个极大线性无关向量集为 $V$ 的一组线性基，简称基。在 OI 中一般而言只会考虑 $n$ 维实线性空间 $\\mathbf{R}^n$ 和 $n$ 维布尔域线性空间 $\\mathbf{Z}_{2}^{n}$。\n如果你对于线性空间与群的关系感兴趣，或者说愿意阅读更多严谨的表述，可以参见 线性空间 - OI Wiki，虽然我觉得不是非常好懂。\n矩阵与线性变换 在线性代数中，向量有列向量和行向量之分，主要研究列向量。对于一个矩阵 $A$，主对角线指的是 $A_{i, i}$ 上的元素，定义单位矩阵 $I$ 表示主对角线上为 $1$，其余均为 $0$。\n$\\text{linear transformation}$ 中的 transformation 一词其实就是 $\\text{function}$ 的意味，而 transformation 寓意着这一关系可以通过某种特定的方式来可视化，定义线性变换为：\n所有直线在变换后仍然保持直线，不能有所弯曲，更进一步，所有“网格线”在线性变化之后仍应该保持平行且等距分布 原点保持固定 实际上，由于线性代数研究中对于线性变化的约束，对于任意一个向量在线性变化后的坐标，只需要通过记录基向量 $\\hat{i}, \\hat{j}$ 变化后的位置。还记得这个式子吗？\n$$ \\begin{aligned}\u0026amp; a \\vec{u} + b \\vec{v} = \\vec{w}, a, b \\in \\mathbb{R} \\ \u0026amp; \\vec{v} = a \\hat{i} + b \\hat{j} \\end{aligned} $$\n在变换之后仍然有：\n$$ \\vec{v}\u0026rsquo; = a \\hat{i}\u0026rsquo; + b \\hat{j}' $$\n获取基向量 $\\hat{i}, \\hat{j}$ 的信息只需要四个数字：变换后的 $x_{\\hat{i}}, y_{\\hat{i}}, x_{\\hat{j}}, y_{\\hat{j}}$。\n把这四个元素丢在一个矩阵里，有一个专有名称称之为 $2 \\times 2$ 矩阵（$\\text{Two-by-Two Matrix}$）：\n$$ \\begin{bmatrix} x_{\\hat{i}} \u0026amp; x_{\\hat{j}} \\\\ y_{\\hat{i}} \u0026amp; y_{\\hat{j}} \\end{bmatrix} $$\n这也就是为什么在线性代数中研究对象通常为列向量。矩阵作为一个载体，记录着一个线性变化的信息，还记得我们对于坐标的标量表示吗？现在我们可以推出矩阵乘向量的表达了：\n$$ \\begin{bmatrix} a \u0026amp; b \\\\ c \u0026amp; d \\end{bmatrix} \\times \\begin{bmatrix} x \\\\ y \\end{bmatrix} = x \\begin{bmatrix} a \\\\ c \\end{bmatrix} + y \\begin{bmatrix} b \\\\ d \\end{bmatrix} = \\begin{bmatrix} ax + by \\\\ cx + dy \\end{bmatrix} $$\n有一种特殊的矩阵形如：\n$$ \\begin{bmatrix} 1 \u0026amp; a \\\\ 0 \u0026amp; b \\end{bmatrix} $$\n这种变换中，$\\hat{i}$ 不发生变化，它有一个特殊的名字为“剪切”（$\\text{shear}$）：\nshear 如果变换后的 $\\hat{i}, \\hat{j}$ 是线性相关的，意味着其中一个向量是另一个向量的某种缩放（倍数关系），这个线性变换将整个二维平面积压在该向量组所在的直线上。\n正如我们上文所说，从动态的视角来看，矩阵是对某空间的一种特定变换。\n矩阵有一种特殊的操作称之为“转置”：在其右上角写上转置 $^{\\boldsymbol{T}}$，表示交换矩阵的行与列。\n矩阵乘法 由上文，线性变换完全取决于对空间内基向量的作用情况，当我们将矩阵和向量相乘时，就是将矩阵所描述的变换作用在向量上。现在我们来看看如何实现一个包含了“旋转”和“剪切”的复合变换：\n$$ \\begin{bmatrix} 1 \u0026amp; 1 \\\\ 0 \u0026amp; 1 \\end{bmatrix}, \\begin{bmatrix} 0 \u0026amp; -1 \\\\ 1 \u0026amp; 0 \\end{bmatrix} $$\n这两个矩阵分别对平面内向量进行 shear 和 rotate 操作，两个矩阵相乘有几何意义：两个线性变化相继作用：\n$$ \\overleftarrow{\\begin{bmatrix} 1 \u0026amp; 1 \\\\ 0 \u0026amp; 1 \\end{bmatrix}, \\begin{bmatrix} 0 \u0026amp; -1 \\\\ 1 \u0026amp; 0 \\end{bmatrix}} $$\n值得注意的是，矩阵乘法从右往左读，为什么？如果我们将矩阵变化看作一个函数，则对于向量 $\\vec{v}$ 的作用有：\n$$ f(g(\\vec{v})) $$\n对于函数的复合，显然是从内往外读，这样理解就自然的多。\n对于两个矩阵中的不同列，我们分别视为元素和变化，抽离出来有：\n$$ \\begin{bmatrix} a \u0026amp; b \\\\ c \u0026amp; d \\end{bmatrix} \\begin{bmatrix} e \u0026amp; f \\\\ g \u0026amp; h \\end{bmatrix} = \\begin{bmatrix} a \u0026amp; b \\\\ c \u0026amp; d \\end{bmatrix} \\times \\begin{bmatrix} e \\\\ g \\end{bmatrix} + \\begin{bmatrix} a \u0026amp; b \\\\ c \u0026amp; d \\end{bmatrix} \\times \\begin{bmatrix} f \\\\ h \\end{bmatrix} = \\begin{bmatrix} a \\times e + b \\times g \u0026amp; a \\times f + b \\times h \\\\ c \\times e + d \\times g \u0026amp; c \\times f + d \\times h \\end{bmatrix} $$\n注意到，矩阵乘法不具有交换律，从几何意义来看显然，举个例子，先旋转再剪切显然不一定等于先剪切再旋转。但是矩阵乘法具有分配律，也就是说：\n$$ \\boldsymbol{(AB)C} = \\boldsymbol{A(BC)} $$\n当然可以继续从几何的层面来思考这个问题，但是我们换个角度，如果拆开来看，将 $\\boldsymbol{AB}$ 视为一个整体，那么无论如何加上括号操作，操作顺序永远是：$\\boldsymbol{C} \\to \\boldsymbol{B} \\to \\boldsymbol{A}$。这样我们就轻松证明出了矩阵乘法重要的性质之一。\n$3 \\times 3$ 的矩阵乘法同理，这里不再赘述：\n$$ \\begin{bmatrix} a \u0026amp; b \u0026amp; c \\\\ d \u0026amp; e \u0026amp; f \\\\ g \u0026amp; h \u0026amp; i \\end{bmatrix} \\begin{bmatrix} x \\\\ y \\\\ z \\end{bmatrix} = x \\begin{bmatrix} a \\\\ d \\\\ g \\end{bmatrix} + y \\begin{bmatrix} b \\\\ e \\\\ h \\end{bmatrix} + z \\begin{bmatrix} c \\\\ f \\\\ i \\end{bmatrix} $$\n行列式 在线性变换中，将坐标新中基向量张开的小正方形面积改变的比例称之为其行列式，记为 $\\det(\\boldsymbol{A})$。\n如果一个二维线性变换的 $\\det = 0$，则说明其将整个空间压缩在了一条线，或者说一个点上。一言概之，如果我们想要知道这个矩阵代表的变换下是否压缩了空间的维度，只需要检验其 $\\det$ 是否为 $0$ 即可。\n但是行列式是可以为负的？如何解释负的 $\\det$ 呢？面积的比例显然不可能为负。\n注意到，将行列式套上绝对值，其仍然表示面积缩放的比例，负号类比物理运动学，代表方向：标志着空间中的定向发生了变化，换而言之，基向量之间的相对位置发生了改变。三维下：\n三维中定向改变了 具体的有右手定则来判断三维空间中定向的改变。\n逆矩阵，列空间，零空间 逆矩阵 $\\boldsymbol{A}^{-1}$ 称为矩阵 $\\boldsymbol{A}$ 的逆矩阵当且仅当 $\\boldsymbol{AA}^{-1} = \\boldsymbol{I}$，或者说，\nnothing 矩阵的引入来自于线性方程组。将线性方程组的系数抽出来，写成矩阵乘法的形式更为方便，而逆矩阵的存在使得我们能够求解方程组，具体的：\n$$ \\boldsymbol{AA}^{-1} \\vec{x} = \\boldsymbol{A}^{-1} \\vec{v} $$\n当 $\\det(\\boldsymbol{A}) \\neq 0$ 时 $\\boldsymbol{A}^{-1}$ 存在，可以使用高斯消元求解。\n注意到即使不存在逆矩阵，方程仍然可能存在解。就是这种清况：\nLucky enough 这里我们引出秩的概念：当变换的结果为一条直线时（一维），我们称这个变换的秩为 $1$。如果变换后的向量落在某个二维平面上，我们称这个变换的秩为 $2$。秩代表着变换后空间的维度。\n列空间是矩阵的列所张开的空间，秩其实是列空间的维数。\nColumn space 有一种特殊的秩：满秩。在这种情况下，秩与列数相等。\n由于线性变换的要求之一是保持原点位置不变，所以零向量一定会包含在列空间中。对于满秩变换：只有零向量会在变换后落在原位置；但如果矩阵非满秩，则会压缩最终空间的维度，这意味着会有一部分向量被变换成了零向量。\n变换后落在原点的向量集合被称之为“零空间”或者核（Kernel）。\n当逆矩阵存在时，我们可以用其求解方程组 列空间让我们得知何时存在解 零空间有助于体现所有可能的解的集合 ","date":"2025-08-06T00:00:00Z","permalink":"https://mizusakuraed.github.io/p/2025-08-06-oi-linear-aligebra-basics/","title":"浅析 OI 中的线性代数基础"}]