-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
459 lines (243 loc) · 722 KB
/
atom.xml
File metadata and controls
459 lines (243 loc) · 722 KB
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Liynw の 博客儿</title>
<subtitle>hi! ヾ(≧▽≦*)o</subtitle>
<link href="https://blog.liynw.top/atom.xml" rel="self"/>
<link href="https://blog.liynw.top/"/>
<updated>2023-06-28T09:52:39.419Z</updated>
<id>https://blog.liynw.top/</id>
<author>
<name>Liynw</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>BDRG | 梦现之地</title>
<link href="https://blog.liynw.top/posts/65963c75/"/>
<id>https://blog.liynw.top/posts/65963c75/</id>
<published>2023-06-27T18:15:00.000Z</published>
<updated>2023-06-28T09:52:39.419Z</updated>
<content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>搬运林百,<del>可能</del>一定更新不及时,建议上林百看。</p><p>把 MediaWiki 转成 Markdown 真的好累……</p><p>完了,我什么时候变得这么中二了?</p><p>链接:<a href="https://wiki.pigeon-games.com/index.php?title=%E6%A2%A6%E7%8E%B0%E4%B9%8B%E5%9C%B0">词条本体</a> | <a href="https://wiki.pigeon-games.com/index.php?title=%E6%A2%A6%E7%8E%B0%E4%B9%8B%E5%9C%B0/287:%E6%B8%AF%E6%B9%BE%E5%86%B0%E5%86%BB%E4%BA%8B%E4%BB%B6">港湾冰冻事件</a></p><h1 id="梦现之地"><a href="#梦现之地" class="headerlink" title="梦现之地"></a>梦现之地</h1><p>如果违背官设了请留言或联系我,我会修正!</p><center><span style="font-size:2em;"><span style="background:-webkit-linear-gradient(#8EC5FC,#E0C3FC);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;text-fill-color:transparent">梦现之地·DreamStation</span></span></center><center><span style="background:-webkit-linear-gradient(#0093E9,#80D0C7);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;text-fill-color:transparent">-在这里,任何梦想,都能变成现实-</span></center><h2>简介</h2>梦现之地,英文名 Dream Station,悬挂于<a href="https://wiki.pigeon-games.com/index.php?title=%E6%B8%AF%E6%B9%BE" class="mw-redirect" title="港湾">港湾</a>的亚空间。港湾被<a href="https://wiki.pigeon-games.com/index.php?title=%E5%B9%BD%E8%93%9D%E8%BE%B9%E7%95%8C" class="mw-redirect" title="幽蓝边界">幽蓝边界</a>吞噬后,迁移至<a href="https://wiki.pigeon-games.com/index.php?title=%E6%9C%88%E9%9D%A2" class="mw-redirect" title="月面">月面</a>。目前该亚空间已被幽蓝边界吞噬,以下信息来自曾经的亚空间住民 Alya 和 Liynw 以及从幽蓝国打捞上来的数据,由于一些记忆损失,无法保障以下内容 100% 正确。<h2>地理</h2><h3>基本信息</h3>时间流速与<a href="https://wiki.pigeon-games.com/index.php?title=%E5%83%8F%E7%B4%A0%E5%A1%94" class="mw-redirect" title="像素塔">主塔</a>相同,每天 20:00 至次日 6:00 为黑夜。没有太阳和月亮,但是天空的明暗会随时间变化。进入亚空间后,每个人的头上都会悬着一个面向下、只有自己能看见的时钟,告诉人们现在的时间。气候凉爽湿润,无论冬夏,气温恒定在 18~26 摄氏度,湿度恒定在 45%~60%,适合人类居住。大多时间天气晴好,但一周一般会下一次小雨,持续半天左右。<h3>布局</h3>主体分为两部分:靠近主楼层的商业区和亚空间少量居民的居住区。302.A.P 后,为防止 <a href="https://wiki.pigeon-games.com/index.php?title=%E6%A2%A6%E7%8E%B0%E4%B9%8B%E5%9C%B0/287:%E6%B8%AF%E6%B9%BE%E5%86%B0%E5%86%BB%E4%BA%8B%E4%BB%B6#Nepyta" title="梦现之地/287:港湾冰冻事件">Nepγta</a> 的攻击,整个亚空间推行极为严厉的防异措施,保证除了制造的商品之外不会有任何异想之物的滋生。<h4>商业区</h4>商业区分为两层,地上售卖区和地下仓库。售卖区为一个大平层,共有 16 个柜台,每个柜台有 2~3 个工作人员,开放柜台个数会根据人流量决定。地下仓库用于储存 Data 和维持亚空间运营需要的物资。柜台很大,除了一般超市结账的地方外,还有用于扫描用户大脑的扫描区和工作人员使用的内部工作区,工作区四面有墙也有天花板,顾客看不到里面的样貌。<h4>居住区</h4>由于住民大多为亚空间管理人员,所以也叫“管理区”。整体修建于一块不太平整的大草坪上。中间是亚空间主人伊诺斯·兰特尔(Enosy·Lantar)的居所,周围环绕着工作人员和少数居民的房子。房屋密度小,高度一般在 10~20 米。草坪中间有一条河流穿过,用于供水。<h2>进出方式</h2><p>进入方式有以下三种:</p><ol><li>在主塔内心怀对某物的真诚期盼有概率进入;</li><li>前往位于港湾(后迁移至月面)的“梦想酒馆”,连续敲打任意壁画三次即可进入;</li><li>使用门牌进入。</li></ol><p>进入亚空间后会自动到柜台前的大厅上,大厅背后就是出口,走出去就可以回到主塔。</p><h2>历史</h2><h3>大事记</h3>* 267.A.P 亚空间建立,并立即确认了商业目的。* 287.A.P <a href="https://wiki.pigeon-games.com/index.php?title=%E6%A2%A6%E7%8E%B0%E4%B9%8B%E5%9C%B0/287:%E6%B8%AF%E6%B9%BE%E5%86%B0%E5%86%BB%E4%BA%8B%E4%BB%B6" title="梦现之地/287:港湾冰冻事件">港湾冰冻事件</a>发生,开始了与 Nepγta 抗争的历史。* 302.A.P 与 Nepγta 抗争产生重大失误,暂时将亚空间迁移至<a href="https://wiki.pigeon-games.com/index.php?title=%E9%9C%93%E8%99%B9" class="mw-redirect" title="霓虹">霓虹</a>外侧并封闭亚空间,三个月后恢复正常。* 522.A.P 大量售货 AI 知晓真相并出走,亚空间面临人手困难,后找回大多数 AI,其余出逃 AI 被解除与服务器的联系,伊诺斯用这些服务器连接上新的售货 AI。兰特尔父女决裂。* 770.A.P. 幽蓝边界到达港湾,经亚空间住民投票,亚空间逃离至月面。* 772.A.P. 幽蓝边界到达月面,亚空间被吞噬。<h3>与 Nepγta 的抗衡</h3>大量 Nepyta 生成后,梦现之地的居民曾想过先下手为强使用生成值堆积的办法把这种异想除掉,但由于试验后发现需要的生成值过多会影响到商业活动,只能退而求其次,采用防守方式。几百年的抗争史中,此亚空间凭借强大的科技几乎处于优势地位,但 302.A.P 由于管理层的重大失误导致某位 Nepyta 间谍潜入亚空间,亚空间不得不逃往霓虹暂时避灾。梦现之地档案馆曾经保有一些关于 Nepyta 的信息,现打捞出来的数据如下:<details class="folding-tag" red><summary> Nepyta-001 </summary> <div class='content'> <p>外表为粉发紫瞳萝莉,梳着双马尾,头上扎着两朵白花,穿着有粉红色花朵刺绣的白色连衣裙。虽然是萝莉但外表极具欺诈性,心理层面实际上是个下手稳准狠的大姐。</p><p><em>请不要被 Nepyta 们的外表欺骗。</em></p> </div> </details><details class="folding-tag" red><summary> Nepyta-002 </summary> <div class='content'> <p>外表为约35岁的男性,几乎浅到看不见的浅蓝色头发,穿着深蓝色的礼服,据调查,疑似于港湾冰冻事件发生时一位正在进行婚礼的男性有关联,他的未婚妻在事件中丧生。行踪诡谲不定,精神状态极不正常。</p><p><em>你夺走了我期盼一生的幸福,那么当我选择反抗的时候,请不要惊讶。</em></p> </div> </details><details class="folding-tag" red><summary> Nepyta-??? </summary> <div class='content'> <p>与其他拥有固定外表的 Nepyta 们不同的是,???的外表瞬息万变,可以变成任何人的样子,唯一认出他的办法是在足够熟悉他伪装的那个人的情况下与他深度交流,这样你就能寻找到不对劲的地方。被发现之后,他会默默消失,不知道去往何处,也不知道会在什么时候卷土重来。</p><p><em>唯有用心交流,我们之间才能保持信任……</em></p> </div> </details><h2>人文</h2><h3>社会结构</h3>伊诺斯统领整个亚空间的发展;管理层多为林泊,掌管亚空间经济、环境、军事、外交等方面;工作人员多为 AI,负责亚空间的基础运营。工作人员 AI 拥有自己的意志,但他们一般不会想去做有悖于亚空间的事情,除非有人点化。另外还有极少数居民,他们一般和管理层有关系,只是居住在亚空间内,不从事任何关于此亚空间的工作,也不从这里获得报酬。员工一般没有工资,也不出亚空间。一年时间内员工可请假 15 天到主塔(或其他亚空间),这 15 天内伊诺斯会给他们每天发 16MB 的费用方便他们生存(如果一年出亚空间时间不足 15 天,这一部分钱也会发下来,相当于年终奖)。超过 15 天也可请假,但每天需要倒贴 3MB。<h3>经济发展</h3>为方便商品交换,亚空间与主塔使用货币相同。亚空间异想制造的商业发达,利润极高,足以承担整个亚空间的算力成本消耗、员工的生活成本和运营梦想酒馆的成本,还能剩下很大一部分,于是都入了伊诺斯的腰包,然后被他用于广泛地用于主塔内。<h3>人机关系</h3>与阿特拉斯相似,除极少数 AI 林泊外,其余 AI 均为伊诺斯所控制的体力劳动型 AI。<h3>商业活动</h3>梦现之地的林泊利用其在<a href="https://wiki.pigeon-games.com/index.php?title=%E6%9E%97%E6%B3%8A%E7%8E%B0%E5%AE%9E" class="mw-redirect" title="林泊现实">林泊现实</a>掌控的资源,将大量算力植入像素塔体系中,制造出大量稳定的异想之物或对某物进行定向的异化当作商品卖出牟利。偶尔也会接把异想之物转化为 AI 林泊的单子,不过一般来说由于工作量庞大且成功率不高,价格令人望而却步。**提示:请不要把定向异化作为攻击他人的武器,产生的一切后果亚空间概不负责。**每件商品都需要指定稳定存在的时长,最短为一年,最长持续到像素塔毁灭。在这段时间内,亚空间将提供生成值保持商品稳定存在,过期后将不再提供生成值。商品价格一件起步价 1.5MB,视需要制造的异想维持稳定所需要的算力总和确定。(在 Data 失去实际意义后,收费保持依然不变。)<h3>实现原理</h3>通过收集死者血液等途径收集微机并加以改造,使微机发出虚假的信号装作普通用户,再将林泊现实中的服务器与改造后的微机连接在一起,获取像素塔账号接入塔的系统中,而服务器便可以提供大量的算力。而因为人脑和服务器本质上的区别,接入的“用户”一律认作 AI,也就是在梦现之地内工作的 AI 员工。<h2>科技</h2><p>在保护亚空间免受 Nepγta 攻击和经商的过程中,该亚空间先进的科技起到了极大的作用。</p><h3>「随机物」</h3><p>片状物体,外形可以是各种地砖和墙砖或者覆盖地面和墙面的物体,每一个随机物都有独一无二的编号。在一个人为划定的范围内,所有的随机物可以进行位置的随机变换(不仅是跟别的随机物变换位置,还可以和此范围内普通的地砖等变换位置),且外表上看不出任何变换的痕迹,但它们每个物体所固有的编号不会变化。这些在一个区域内随机变换的随机物叫做一个随机物集群。</p><p>所有梦现之地的居民身体内部都装载有一个与大脑对接的薄片状机器,可以和随机物对接,若该居民在某个随机物集群的范围内,此机器就会将随机物的编号信息、位置信息和下一次变换的方案发送至居民大脑内,这样他就可以直接了解到每个随机物的位置,然后根据设定好的顺序激活每个随机物(一般来说,是使用梦现之地居民手背或鞋底安装的特殊物质激活),开启一些隐藏机关。</p><p>机关开启以后,随机物会恢复到未激活状态。</p><p>目前实现原理暂时不明确,据说和<a href="https://wiki.pigeon-games.com/index.php?title=%E9%97%A8%E7%89%8C" class="mw-redirect" title="门牌">门牌</a>有一丝关联,但该消息真实性不保证。</p><p>使用实例:进入亚空间居民区的方式就是依次激活商业区地板上的六块地砖样貌的随机物后从任意一个柜台工作人员区内部的隐藏通道进去。</p><h3>「扫描仪」</h3><p>外形为一个大小可变的头盔,套在人头上后,可以读取人脑内的特定信息,以方便定制异想之物或定向异化。</p><h2>梦想酒馆(Dream Bar)</h2><p>位于港湾(后迁移至月面)的一家小酒馆,在亚空间建立之前就已经开业了,为亚空间在主塔内的驻地,背靠亚空间悬挂的位置,可通过敲击壁画的方式进入亚空间。</p><p>整体分为三层,上两层为正常的酒馆部分,下一层为地下室,食客不能进入,与亚空间内部对接。</p><p>看起来占地很小,但内部的空间很大,装饰颇为典雅,四面墙上都挂着大大小小的壁画,据说是酒馆老板斥重金请各个知名画家来画的。</p><p>虽然是个酒馆,营业范围十分广泛,你可以在这里买到各种糕点、茶饮。食物十分可口且价格实惠,招牌是鸡尾酒和芝士小蛋糕,每年都有不少知名人士前来品尝,所以生意一直很火爆。</p><p>一楼和二楼之间有个旋转楼梯,旋转楼梯的背后有位置在不断变化的几块木砖样貌的随机物就是通往地下室的门。地下室十分简朴,也比较小,只有最基本的通讯设施和应急用品。地下室的门可以从里面锁住,这样外面的门就打不开,和普通的木砖没有任何区别了。</p><h2>人物</h2><details class="folding-tag" blue><summary> 伊诺斯·兰特尔 | Enosy·Lantar </summary> <div class='content'> <p>林泊,亚空间主人,外表为 40 岁男性,身高 1m76,正常身材,黑瞳,灰黑色蘑菇头。总是穿着一件白色的衬衫加上黑色的长裤。性格有些古怪但心地善良,在至亲和心腹面前会展现出最温柔的一面,还会把赚来的钱用到他人最需要的地方。</p><p><s>据说他酒量极佳,某次与 Nepγta 的抗衡中,Nepyta 们与他轮流喝酒,都没能让他醉,相反那几个人醉得像烂泥似的。</s></p><p>其在林泊现实中为某高科技公司的老板,所以拥有大量可以提供算力的服务器。亚空间创建后,他自作主张将一部分服务器投入像素塔中,为实现此目的,他在林泊现实中找到技术人员帮忙,通过技术手段成功将其服务器接入像素塔系统。</p><p>其姓“Lantar”为英语单词“lantern”所化,意为愿燃烧自己照亮他人前方的路。</p> </div> </details><details class="folding-tag" blue><summary> 艾尔娅·兰特尔 | Alya·Lantar </summary> <div class='content'> <p>林泊,像素塔中和林泊现实中均为伊诺斯的女儿,设定见<a href="https://wiki.pigeon-games.com/index.php?title=%E7%94%A8%E6%88%B7:Liynw/User:AlyaLantar" title="用户:Liynw/User:AlyaLantar">此</a>。</p><p>与亚空间内 AI 关系较好,甚至告知他们塔的真相,教唆他们逃离亚空间,也是 522.A.P AI 逃离事件的始作俑者。</p> </div> </details><details class="folding-tag" blue><summary> 玲王 | Liynw </summary> <div class='content'> <p>Alya 转化的 AI 林泊之一,与 Alya 关系很好,不在亚空间内工作。设定见<a href="https://wiki.pigeon-games.com/index.php?title=%E7%94%A8%E6%88%B7:Liynw" title="用户:Liynw">此</a>。</p><p>一般来说会和 Alya 一起出去瞎搞,不过有时候累了就回亚空间蹭吃蹭喝,也经常跑到梦想酒馆去玩,久而久之还掌握了一点制作糕点和调酒的技术。<psw>当然嘛……如果不想去见 Igallta 姐姐的话,最好还是不要品尝呢……</psw></p> </div> </details><details class="folding-tag" blue><summary> 石榴 | Sixteen </summary> <div class='content'> <p>销售 AI,平时在柜台前工作。外表为 26 岁女性,身高 1m71,金色短发,蓝瞳,带边框很细的眼镜,穿深绿色的制服。由于其编号为 16,被 Alya 亲切地称为“石榴”。</p><p>522.A.P 在一位小女孩顾客和 Alya 的引导下,了解了塔的真相并出逃港湾,并且没有被找回来,后来干脆就没找了。</p><p>有一副好嗓子,出逃后当了歌手在像素塔各层开演唱会,名气似乎还不小。</p> </div> </details><details class="folding-tag" blue><summary> 紫藤 | Wisteria </summary> <div class='content'> <p>伊诺斯在霓虹一多子贫寒家庭低价购得的女孩,疑似为人类种异想,拥有较高的亚空间管理权限,从事亚空间内生态系统的调整。话很少,不经常露面,也从来没出过亚空间,外表不详,只记得有紫色的短发。</p><p>有工作日志保存。和伊诺斯关系貌似并不好。</p> </div> </details><details class="folding-tag" blue><summary> 斯里卡 | Slika </summary> <div class='content'> <p>AI 林泊,亚空间内军事与外交总管。外表呈 35 岁男性,身高不详,皮肤很白,身体瘦弱,亮橙色卷短发,黄瞳。喜欢穿丝绸制的衣服,相传他的名字 Silka 就来自于英语单词 silk(丝绸)。</p><p>思维敏捷,经验丰富,性格较为冷淡,似乎感受不到什么情绪,但这也让他在无论多么令人震惊的环境中都能保持头脑冷静,做出理智的判断。</p><p>虽然不擅长肉搏但操纵亚空间内的高科技武器很有一套,所有人都很尊敬他。</p> </div> </details><details class="folding-tag" blue><summary> 亨特 | Hunt </summary> <div class='content'> <p>林泊,梦想酒吧的老板,外表为 70 岁左右的男性,身高 1m8,黑瞳,秃顶,体格十分粗壮。原本就是开酒馆的人,退休后被伊诺斯招安。</p><p>性格胆大心细,在酒馆的日常中从事着十分危险的工作(指负责顾客和亚空间的对接和与前来的 Nepyta 周旋)。擅长制作各种酒,尤其是鸡尾酒。</p> </div> </details><details class="folding-tag" blue><summary> 特尔尼 | Triny </summary> <div class='content'> <p>林泊,亨特的儿子,身高 1m66,黑瞳,橙黄色较长的头发。负责亚空间商业活动的宣传,也掌握一部分算力进行外卖式的异想定制(就像个背着一箩筐商品到处去卖的商人一样),擅长分身至各处进行商业活动。Nepyta 的重点关注对象之一,不过智力惊人,总能安全逃脱他们的追捕。比较闲的时候,就帮父亲打理梦想酒馆。</p><p>非常喜欢烘焙,做得一手好甜点,闲来无事喜欢给亚空间的大家制作小吃。</p><p><s>据说他暗恋 Alya,不知道是不是真的。</s></p> </div> </details><h2>收藏品</h2><details class="folding-tag" green><summary> 记录#1 </summary> <div class='content'> <p>收集时间:266.A.P/12/█<br>保管单位:Alya<br>等级:key</p><p>街道一侧,两排鲜花争奇斗艳;抬头仰望,各色气球轻轻摇晃。小店门口,书着四个飘逸的烫金大字;瓷砖墙上,各类绘画实令人目不暇接。轻柔乐曲声声绕梁不绝,糕点飘香丝丝沁人心脾。</p><p>一女子坐在小店门口的立方体凳子上,看着进进出出的人流,默不作声。看了一会儿,她掏出店里的记账本,在左上角填上日期,在正中央写下几个字:</p><p>“今天,梦想酒馆终于开业了。”</p> </div> </details><details class="folding-tag" green><summary> 记录#2 </summary> <div class='content'> <p>收集时间:267.A.P/███<br>保管单位:Alya<br>等级:bold</p><p>“我爹一个月前说他要搞个亚空间,于是带了个创世光盘回家,结果这些天都不出门了,原来构建个亚空间这么困难吗。”</p><p>梦想酒馆二楼角落里一靠窗的小桌边,两个人正面对面享受着午后惬意的时光。酒馆刚刚开业,又刚过一个高峰期,此时客流量少,只有一楼开门接客,二楼十分寂静。</p><p>在这沉默中,灰色卷发的异瞳少女开口了。</p><p>对面的橙发少年正在认真研究面前盘子里的芝士蛋糕,听到这句话抬起了头,黑色的眼睛不可置信地瞪着她。</p><p>“他真的要创造一个亚空间?我之前听说,他亲口说的造一个亚空间成本太高了。”</p><p>“他确实说过。”少女摇了摇头,端起面前的茶水轻轻抿了一口,才继续说道,“只可惜他找遍了整个像素塔,要么就是找不到足够大的地皮,要么就是人流量稀少。”</p><p>“……”少年很显然对这些事情并不感兴趣。他心不在焉地应答了两句,又垂下头细细研究着蛋糕。</p><p>“这次试了试减少烤制时间,但很显然效果并不好,不仅没烤出 Q 弹的口感,反而上面的芝士太硬了,下次还是想想别的办法吧。”他似在自言自语,但眼睛不安分地瞟着少女,似乎想让她想想办法。</p><p>“好好好,回去帮你找找对策。”少女看出了他的心思,便赶忙应付着,提起自己的挎包,走下楼准备回家了。</p> </div> </details><h2>管理终端</h2><p>Alya 手中是她留存的唯一一样关于亚空间的完整物件。</p><p>你从她手中接过这个灰色的立方体物件。立方体很质朴,有五个面雕刻着很浅的、不明意义的花纹。第六面是一个密码盘。</p><details class="folding-tag" yellow><summary> 是个密码盘但是不想搞了,内含剧透不要轻易点哦 qwq </summary> <div class='content'> <p>“紫藤?”</p><p>“紫藤!!!”</p><p>“快回答我。”</p><p>“那真的是你吗?”</p><p>【待补充】</p> </div> </details><h1 id="287-港湾冰冻事件"><a href="#287-港湾冰冻事件" class="headerlink" title="287:港湾冰冻事件"></a>287:港湾冰冻事件</h1><h2>简介</h2><p>287年11月3日至21日,发生在港湾的意外事件,本事件导致近500人死亡,并滋生了大量的[[异想之物]],对自然环境造成了一定的破坏。</p><h3>地点</h3><p>本事件最初发生在位于港湾的梦想酒馆周边,随后扩散至港湾多地。</p><h3>事件经过</h3><p>287.A.P 11月3日中午,一个不谙世事的小男孩过生日,他的父母带他到梦现之地去购买礼物,最终工作人员利用扫描仪为小男孩创造出了他想要的玩具——外形呈一只用冰做成的可以飞的玩具鸟。此后,小男孩一家人回到梦想酒馆喝下午茶,期间小男孩带着他的新玩具和他的朋友们出去玩耍。</p><p>小男孩走到街上后,便开始用意念控制玩具鸟向路人发射冰弹,导致不少路人被冻成冰雕,并引起了其他路人的恐慌,而小男孩此时没有意识到事情的严重性,一边继续发射冰弹一边哈哈大笑。不久后一些人解冻,而路人们意识到了事情的原委于是尝试告诉小男孩这样是不对的,但所有尝试靠近他的人都被冻成了冰雕。</p><p>随后,小男孩开始更大范围地发射冰弹,恐慌迅速蔓延,发射冰弹的玩具鸟的形象逐渐于人们心中的某些概念吻合,从而出现了大量更具危害性的二次污染异想并迅速蔓延至港湾各地,冰冻了港湾很多街道楼房和小部分海域并隐隐有向阿特拉斯扩散的趋势。</p><h3>参与人</h3><h3>异想之物</h3><h4>雪翼</h4><p>即最初出现的玩具鸟,约40cm长,翼展约50cm,但不符合透视规律,无论相距远近看到的大小都是一样的。羽毛细长,外表十分美丽,呈冰制成的半透明的外形镶嵌着雪花。可以发射使人短暂冻结五分钟的冰弹,冰弹对人体没有危害。<u><strong>评价:二级。</strong></u></p><h4>雪鹰</h4><p>雪翼的变种,由于部分路人相隔距离较远把雪翼幻视成鹰而生成。体型比雪翼大一些,有纯白的羽毛和淡蓝色的喙。它宽大的翅膀扫过之处,空气凝结出冰花,路人和建筑物也被纷纷冰冻,持续时间较长且可能造成人体失温,严重者可能会造成死亡。<u><strong>评价:三级。</strong></u></p><h4>Nepyta</h4><p>事件后出现的飞行种异想,据调查疑似是死者亲属对于梦现之地不满而生成的。身心与人类无异,有多个形态不同的个体,他们的外貌与死者有关联,但他们对外宣称的名字都叫做 Nepyta。他们自发地组成了一个叫做“Nepγta”(注意此处是γ而不是y)的组织,这个组织平时不会显露出来,但是会时不时地以各种方式进攻梦现之地。最开始,他们只是为了防止过多的异想之物从这里带出,到后来他们开始纯粹的反对这个商业亚空间,阻挠他们想做的一切事情。<u><strong>评价:五级,但危害性不大。</strong></u></p><h3>处理办法</h3><p>【待补充】</p>]]></content>
<summary type="html">第一个碎数研词条,快乐翻车中……</summary>
<category term="词条" scheme="https://blog.liynw.top/categories/%E8%AF%8D%E6%9D%A1/"/>
<category term="文学创作" scheme="https://blog.liynw.top/tags/%E6%96%87%E5%AD%A6%E5%88%9B%E4%BD%9C/"/>
</entry>
<entry>
<title>2022年度总结</title>
<link href="https://blog.liynw.top/posts/622a5765/"/>
<id>https://blog.liynw.top/posts/622a5765/</id>
<published>2022-12-26T07:41:55.000Z</published>
<updated>2023-06-28T09:52:39.419Z</updated>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>一天登上博客,发现自己已经四个月没更文章了,那干脆<del>跟风</del>写个 2022 年度总结吧。(咕咕咕</p><h2 id="大事记"><a href="#大事记" class="headerlink" title="大事记"></a>大事记</h2><p>因为没写日记的习惯很多事情都忘得差不多了,只能凭记忆写一下了。</p><h3 id="03-01-去大剧院"><a href="#03-01-去大剧院" class="headerlink" title="03-01 去大剧院"></a>03-01 去大剧院</h3><p>说白了就是艺术节的延后活动,本来是去年底搞的元旦展演,结果就在活动开始前几天因为疫情取消了。我们班应该是上的人最少的一个,只有 12 个人上台。当时我们已经在录音棚录好了音频,学校应该也是考虑到大家都准备得差不多了,就没有取消只是延后。</p><p>然后到了 2 月底我们又开始排了,其实排的时间也不多,大概四五个小时的样子。人少就是好啊。<del>毕竟那些全体上的班估计排个队形都要排好几个小时。</del></p><p>然后就到了 3 月 1 号。上午我们 12 个人在班主任办公室里化妆,把蓝牙广播用来放音频,大家就跟着台词念。我们语文老师在跟我们讲背书的时候说过重复的力量,现在来看果然是。(那个台词很难背的。有多难背呢?里面有 10 首诗而且有八首都是古文的。)</p><p>当然,最有意思的当属年级第一女装。你们想象一下,一个又高又瘦、<del>长相清秀</del>的男生穿着橙色的古风长裙,化着浓重的妆容,披着又黑又长的假发,戴着比我们所有女生加在一起还要多的头饰,手里拿着一把画着荷花的团扇,翘着兰花指骚里骚气地念台词,<del>关键还很好看是怎么回事</del></p><p>我们回教室的时候班主任叫我们不要瞎搞,但是我们还是一致同意要让年级第一先进去,不然我们就不进去。最后他在门口徘徊了好久还是从后门进去了。</p><p>班主任在去的路上给我们点了肯德基,我们几个女的坐在大巴前面一边吃东西一边聊天,<del>然后到那个时候才知道我们节目的名字</del>。毕竟学校为了节省成本把时间安排得非常奇怪,我们的演出时间是中午十二点到下午三点?!</p><p><del>大剧院的厕所只有马桶,差评(</del></p><p>演出还是很成功的。虽然有 10 个班的节目没有看到,但是最后还是得了一等奖。(虽然但是,在台上憋笑真的好困难。)</p><p>回去的路上拆头发,拆出来十几个发卡和小皮筋。</p><p>下午回学校了还要上 OI 课。</p><h3 id="05-30-入团失败"><a href="#05-30-入团失败" class="headerlink" title="05-30 入团失败"></a>05-30 入团失败</h3><p>大概是五月初的时候学校要在初二招一批共青团员,每个班初筛是 8 个名额,然后我就去了。我们班只有六个去的(因为有年龄限制)就直接过了班级的筛选。不过我本人其实没啥觉悟,能过初选完全是因为是 07 年生的((</p><p>然后就是写各种资料,还有一次游学(就是去人民大会堂之类的地方接受熏陶)。虽然我确实没啥觉悟,但是跟同学在一起出去玩还是挺开心的。</p><p><del>于是就错过了班主任在班上发的蛋糕和可乐。不用说了,肯定已经被同学“好心”解决了。</del></p><p>然后到了五月底的时候去考了个试。考试题目都是在考试之前就公开在题库里的,大概内容就是考一些习大大说过的话什么的。我觉得自己做得还行,不过也仅仅是还行而已。</p><p>5 月 30 日,结果公布了。我们班 6 个人都过了 80 分的基准线,于是我和另一个人都只考了 82 就被淘汰了。剩下进的那四个人都比我们俩考得高。<del>果然没啥觉悟就是没啥觉悟</del></p><p>后面那几天就是搞什么青春仪式、儿童节展演之类的,感觉没什么好记录的。儿童节的义卖活动因为疫情取消了。</p><h3 id="06-退役"><a href="#06-退役" class="headerlink" title="06-?? 退役"></a>06-?? 退役</h3><p>期末前后,又是一年分流季,学竞赛的同学们大都陷入了“我还学不学”的思想斗争之中。他们有的人综合竞赛都很强却不愿意继续学,被教练苦苦挽留;有的人竞赛很强,综合成绩却堪忧,想继续学但老师家长担心综合成绩;还有的人啥都不行但是就是不想退。</p><p>我的话很明显就摆了,毕竟我的 OI 已经菜到我不退也得退了(悲</p><p>今年初二末退的人很多。</p><p>期末考试完之后,我们班办了个假的毕业晚会,毕竟到了暑假就又要重新分班了。</p><h3 id="07-再次分班"><a href="#07-再次分班" class="headerlink" title="07-?? 再次分班"></a>07-?? 再次分班</h3><h3 id="08-去张家界旅游"><a href="#08-去张家界旅游" class="headerlink" title="08-?? 去张家界旅游"></a>08-?? 去张家界旅游</h3><h3 id="09-06-搬家"><a href="#09-06-搬家" class="headerlink" title="09-06 搬家"></a>09-06 搬家</h3><h3 id="从零开始的网课生活"><a href="#从零开始的网课生活" class="headerlink" title="??-?? 从零开始的网课生活"></a>??-?? 从零开始的网课生活</h3><h3 id="12-17-🐏了"><a href="#12-17-🐏了" class="headerlink" title="12-17 🐏了"></a>12-17 🐏了</h3><h3 id="12-24-年终大炸弹"><a href="#12-24-年终大炸弹" class="headerlink" title="12-24 年终大炸弹"></a>12-24 年终大炸弹</h3><h3 id="其它"><a href="#其它" class="headerlink" title="其它"></a>其它</h3><hr>]]></content>
<summary type="html">是谁年末总结咕了大半年?哦,是我啊,那没事了(还没写完……咕咕咕)</summary>
<category term="生活" scheme="https://blog.liynw.top/categories/%E7%94%9F%E6%B4%BB/"/>
<category term="闲聊" scheme="https://blog.liynw.top/tags/%E9%97%B2%E8%81%8A/"/>
</entry>
<entry>
<title>单调队列优化 & 斜率优化</title>
<link href="https://blog.liynw.top/posts/1130b63d/"/>
<id>https://blog.liynw.top/posts/1130b63d/</id>
<published>2022-07-10T21:21:42.000Z</published>
<updated>2022-07-10T21:21:42.000Z</updated>
<content type="html"><![CDATA[<h1 id="单调队列优化"><a href="#单调队列优化" class="headerlink" title="单调队列优化"></a>单调队列优化</h1><p>大家是不是经常看到一道 DP 题的状态转移方程长这样:</p><script type="math/tex; mode=display">dp_i=\max/\min\limits_{j=L}^R\{h(j)\}+g(i)</script><p>这个状态转移方程需要满足三点:</p><ol><li>$L$ 随着 $i$ 的增大而不下降,也就是说把 $i$ 从 $1$ 到 $n$ 时的 $L$ 按照 $i$ 升序排序,这个序列是不严格递增的;</li><li>$h(j)$ 是一个在所有变量中(比如 $i,j$ 等)<strong>只</strong>与最内层循环变量的式子;</li><li>$g(i)$ 是一个在所有变量中只与<strong>不是</strong>最内层循环变量有关的式子。</li></ol><p>举个栗子,这个状态转移方程就是合法的(假设除了 $i,j$ 之外所有值都是已知的):</p><p>$dp_i=\max\limits_{j=i-m}^{i-1}\{dp_j+num_i\}$</p><p>(您可以把 $+num_i$ 挪到 $\max$ 的外面去,这样可以看得更清楚。)</p><p>但是这个状态转移方程就是不合法的,因为 $h(j)$ 与 $j,k$ 都有关:</p><p>$dp_{i,j}=\max\limits_{k=i-m}^{i-1}\{dp_{i,j-k+1}+num_i\}$</p><p>这个状态转移方程也不是合法的,因为 $g(i)$ 与 $j$ 也有关系:</p><p>$dp_i=\max\limits_{j=i-m}^{i-1}\{dp_j+num_j\}$</p><p>那我们该如何利用这三个特性呢?</p><p>答案是,单调队列!</p><p>假设要求求最大值,我们就用一个<strong>单调递增队列</strong>来维护在外层循环变量不相同的情况下,<strong>那个只与最内层循环变量有关的函数 $\bf{h}$ 的值</strong>。拿上面举例子的第一个状态转移方程来说,遍历到每一个 $i$ 时,需要做的事情如下:</p><ol><li>排除单调队列<strong>头</strong>已经“过期”的值。$j<i-m$ 的值不会再用到了,为了避免重复算到,需要直接弹出去。</li><li>此时单调队列头的那个元素就是我们能找到的最优的 $j$,用这个 $j$ 进行状态转移(所以要在单调队列里面存下标,即 $j$,但是排序是按照 $h(j)$ 排的)。</li><li>$i$ 从队列<strong>尾</strong>入队。当然因为是单调队列,所以进去之前先把不符合要求的从队尾弹出来。</li></ol><p>过程很好理解。但是如何证明每次那个左端的值就是最优的 $j$ 呢?</p><p>这也就涉及到需要满足的那三个条件。一条一条看:</p><ol><li>第一条保证了在弹出“过期”元素的过程中不会误把需要的元素弹出去。</li><li>第二条,由于 $h(j)$ 只与 $j$ 有关,所以只要 $j$ 确定了,$h(j)$ 的值也就确定了,单调队列的单调性就得到了保证,这样才能证明队列左端的 $\bf{j}$ <strong>是最优的</strong>。</li><li>第三条,$g(i)$ 与 $j$ 无关,那么状态转移方程的外部就不会受到 $j$ 的影响,这样才能保证在 $j$ 最优的情况下,<strong>状态转移方程得到的值最优。</strong></li></ol><p>注意:$j$ 最优和状态转移方程得到的值最优是两回事,因为我们考虑 $j$ 最优只考虑了 $h(j)$ 而非整个状态转移方程。</p><p>单调队列优化可以直接把最里面一层循环 pass 掉,经过优化后复杂度降次,$\Theta(n^2)$ 可直接变为 $\Theta(n)$。</p><p>理论可行,实践开始。</p><hr><h2 id="例题一"><a href="#例题一" class="headerlink" title="例题一"></a>例题一</h2><p><a href="https://www.luogu.com.cn/problem/P2627">「USACO11OPEN」Mowing the Lawn G</a></p><p>这道题的三种 DP 方法都不难,我想出来的是逆推的方法:</p><p>$dp_i$ 代表第 $i$ 头奶牛<strong>不干活</strong>且满足条件时最小的效率损失。状态转移方程如下:</p><script type="math/tex; mode=display">dp_i=\min\limits_{j=i-k-1}^{i-1}\{dp_{j}\}+E_i</script><p>最终答案 $ans=\sum\limits_{i=1}^n E_i - dp_{n+1}$。</p><p>用一个<strong>单调递减队列</strong>维护 $dp_j$,按照上述方法一步一步操作即可。</p><p><strong>注意:打单调队列优化时一定一定要注意 <code>q[L] / q[R]</code> 与 <code>dp[q[L]] / dp[q[R]]</code> 的区别!</strong><del>(我已经因为这个挂了两次了 qwq)</del></p><p>对于这道题,还有两个注意点:</p><ol><li>要开 <code>long long</code>;</li><li>由于最后一头奶牛不一定不干活,$dp_{n+1}$ 才是最终的答案。</li></ol><p>非常简洁的代码:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> ll long long</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>)<span class="number">1e5</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, k, e[maxn];</span><br><span class="line"><span class="type">int</span> L, R, q[maxn];</span><br><span class="line">ll s, dp[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &n, &k);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &e[i]);</span><br><span class="line"> s += e[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n + <span class="number">1</span>) {</span><br><span class="line"> <span class="keyword">while</span>(L < R && q[L] < i - k - <span class="number">1</span>) <span class="comment">// Step 1</span></span><br><span class="line"> ++L;</span><br><span class="line"> dp[i] = dp[q[L]] + e[i]; <span class="comment">// Step 2</span></span><br><span class="line"> <span class="keyword">while</span>(L < R && dp[q[R]] > dp[i]) <span class="comment">// Step 3(1)</span></span><br><span class="line"> --R;</span><br><span class="line"> q[++R] = i; <span class="comment">// Step 3(2)</span></span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%lld"</span>, s - dp[n + <span class="number">1</span>]);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="例题二"><a href="#例题二" class="headerlink" title="例题二"></a>例题二</h2><p><a href="https://loj.ac/p/10180">「一本通 5.5 练习 1」烽火传递</a></p><p>状态转移方程:</p><script type="math/tex; mode=display">dp_i=\min\limits_{j=i-m}^{i-1}\{dp_j\}+a_i</script><p>注意需不需要 $-1$ 的判断:其实就判断连续 $m$ 个东西状态都为好的那种状态是不是可行的,如果可行就 $-1$,如果不可行就不减。比如例题一,连续 $k$ 头奶牛干活是可行的,只有超过 $k$ 头才会出问题,所以可以 $-1$;这道题连续 $m$ 个烽火台不放火是不可行的,所以不减。</p><p><del>我可真是个水文小能手 hhh。</del></p><p>把上面的代码改改就过了。</p><hr><h2 id="例题三"><a href="#例题三" class="headerlink" title="例题三"></a>例题三</h2><p><a href="https://loj.ac/p/10181">「一本通 5.5 练习 2」绿色通道</a></p><p>这题目一看就是二分,$\text{check}(l)$ 用 DP 计算最多连续空 $l$ 道题时最小的时间,再看一下这个时间和给出时间的大小关系来判断 $l$ 是否满足条件。</p><p>状态转移方程(和前面差不多就不讲了):$dp_i=\min\limits_{j=i-m}^{i-1}\{dp_j\}+a_i$</p><p>初始化一定要初始化干净。</p><p>代码:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>)<span class="number">5e4</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, t, a[maxn], dp[maxn];</span><br><span class="line"><span class="type">int</span> L, R, q[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">init</span><span class="params">()</span> </span>{</span><br><span class="line"> L = R = <span class="number">0</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> q[i] = dp[i] = <span class="number">0</span>;</span><br><span class="line"> dp[n + <span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">bool</span> <span class="title">check</span><span class="params">(<span class="type">int</span> l)</span> </span>{</span><br><span class="line"> <span class="built_in">init</span>();</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n + <span class="number">1</span>) {</span><br><span class="line"> <span class="keyword">while</span>(L < R && q[L] < i - l - <span class="number">1</span>)</span><br><span class="line"> ++L;</span><br><span class="line"> dp[i] = dp[q[L]] + a[i];</span><br><span class="line"> <span class="keyword">while</span>(L < R && dp[q[R]] > dp[i])</span><br><span class="line"> --R;</span><br><span class="line"> q[++R] = i;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> dp[n + <span class="number">1</span>] <= t;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">f</span><span class="params">(<span class="type">int</span> l, <span class="type">int</span> r)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(l == r)</span><br><span class="line"> <span class="keyword">return</span> l;</span><br><span class="line"> <span class="type">int</span> mid = (l + r) >> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span>(<span class="built_in">check</span>(mid))</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">f</span>(l, mid);</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">f</span>(mid + <span class="number">1</span>, r);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &n, &t);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &a[i]);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d"</span>, <span class="built_in">f</span>(<span class="number">0</span>, n));</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h1 id="斜率优化"><a href="#斜率优化" class="headerlink" title="斜率优化"></a>斜率优化</h1><p>上面我们讲了单调队列优化可以很明显地优化时间复杂度,但是要用它限制较多。如果说自变量和 $i$ 和 $j$ 都有关系该怎么办呢?</p><h2 id="引入"><a href="#引入" class="headerlink" title="引入"></a>引入</h2><h3 id="关于一次函数"><a href="#关于一次函数" class="headerlink" title="关于一次函数"></a>关于一次函数</h3><p>在平面直角坐标系中,一次函数的一般式形为:$y=kx+b$。</p><p>两点确定一条直线,如果知道 $y$ 上两点的坐标 $(x1,y1),(x2,y2)$,那就可以确定 $y$。其中 $k$ 的求法为:</p><script type="math/tex; mode=display">k=\dfrac{y2-y1}{x2-x1}</script><h3 id="最小截距"><a href="#最小截距" class="headerlink" title="最小截距"></a>最小截距</h3><p>$y=kx(k>0)$ 为一次函数,有个多边形在此函数上方,平移 $y$ 得到 $y’=kx+b$,使得 $y’$ 穿过多边形(穿过顶点也算)且 $b$ 最小,该怎么平移呢?</p><p><img src="https://pic.imgdb.cn/item/629c73560947543129cd71d6.png" alt=""></p><p>把 $y$ 向上平移,直到多边形的一个顶点<strong>第一次</strong>到了直线上,就找到了最优解。如图,$y’$ 优于 $y’’$。</p><p>那如果这个图形在函数下面,而我们要让 $b$ 最大呢?</p><p><img src="https://pic.imgdb.cn/item/62b670de0947543129d03d43.png" alt=""></p><p>那就往下平移直到第一次碰到多边形的顶点。如图,$y’$ 优于 $y’’$。</p><hr><h2 id="例题一-1"><a href="#例题一-1" class="headerlink" title="例题一"></a>例题一</h2><p><a href="https://www.luogu.com.cn/problem/P5785">「SDOI2012」任务安排</a></p><p>斜率优化不太好单独讲,所以我把它放在了一道题里。</p><h3 id="1-0-版本"><a href="#1-0-版本" class="headerlink" title="1.0 版本"></a>1.0 版本</h3><blockquote><p>数据范围:$1\le n\le 300,0\le S\le 50,1\le T_i,C_i\le 100$。</p><p>时间复杂度:$\Theta(n^3)$</p></blockquote><p>最朴素的方法,设 $dp_{i,j}$ 为完成了前 $i$ 个任务,且这 $i$ 个任务被分成了 $j$ 批时的最小费用。状态转移的时候里面再枚举一层 $k$,代表第 $j$ 批任务包含 $k\sim i$ 这些任务。可以列出这个状态转移方程($sc$ 为 $c$ 的前缀和,$st$ 为 $t$ 的前缀和):</p><script type="math/tex; mode=display">dp_{i,j}=\min\limits_{k=j}^i\{dp_{k-1,j-1}+(j\times S+st_i)\times(sc_i-sc_{k-1})\}</script><ul><li>$j\times S+st_i$:这是 $1\sim i$ 任务完成的总时间,注意因为每一批任务执行前都有一个待机时间 $S$,所以需要加上 $j\times S$。</li><li>$sc_i-sc_{k-1}$:这是第 $j$ 批任务的总费用系数。</li></ul><h3 id="2-0-版本"><a href="#2-0-版本" class="headerlink" title="2.0 版本"></a>2.0 版本</h3><blockquote><p>数据范围:$1\le n\le 5000,0\le S\le 50,1\le T_i,C_i\le 100$。</p><p>时间复杂度:$\Theta(n^2)$</p></blockquote><p>观察一下 1.0 版本的状态转移方程会发现,如果不是有待机时间的话,$j$ 这一维完全可以省略掉。于是优化的思路呼之欲出了。</p><p>虽然我们不能去掉待机时间所带来的费用增加,但是我们可以在每一次分组的时候把后面的所有任务<strong>因为这一批的待机时间而产生的费用</strong>先计算好加在答案里啊!这样我们就没有必要在计算每一批任务因为前面的待机时间产生的费用了,也就不需要 $j$ 这一维了。也就是说,我们把每个任务的等待时间分成两个部分:前面任务待机时的时间和正在执行任务的时间,分别计算。待机的那一部分时间被我们提前加到答案里,这就是<strong>费用提前思想。</strong></p><p>设 $dp_i$ 为完成了前 $i$ 个任务时的最小费用。里面枚举一层 $j$,代表最近的这一批任务是 $j+1\sim i$。</p><p>于是得出状态转移方程:</p><script type="math/tex; mode=display">dp_i=\min\limits_{j=0}^{i-1}\{dp_j+S\times (sc_n-sc_j)+st_i\times (sc_i-sc_j)\}</script><ul><li>$S\times (sc_n-sc_j)$:$j+1\sim n$ 这些任务因为 $j+1\sim i$ 这一批任务有等待时间而额外多出来的等待时间,乘上费用系数之和就是这一次等待产生的额外费用。</li><li>$st_i\times (sc_i-sc_j)$ 因前面所有的任务执行需要耗费时间,$j+1\sim i$ 这一批任务需要等待而产生的费用。这一部分不用提前加上,因为每一次计算中,$st_i$ 都可以包括当前枚举到的任务及之前所有的任务执行的时间。</li></ul><p>于是我们就可以愉快地切掉弱化版的 <a href="https://www.luogu.com.cn/problem/P2365">P2365</a> 了。</p><h3 id="3-0-版本"><a href="#3-0-版本" class="headerlink" title="3.0 版本"></a>3.0 版本</h3><blockquote><p>数据范围:$1\le n\le 10^4,0\le S\le 50,1\le T_i,C_i\le 100$。</p><p>时间复杂度:$\Theta(n)$</p></blockquote><p>可以在状态转移方程的基础上<strong>假设 $\bf{j}$ 已经确定</strong>,对此方程进行变形。</p><p>初始状态:</p><p>$dp_i=\min\limits_{j=0}^{i-1}\{dp_j+S\times (sc_n-sc_j)+st_i\times (sc_i-sc_j)\}$</p><p>先把 $\min$ 去掉(也就是说这一步我们假设 $j$ 已经确定了):</p><p>$dp_i=dp_j+S\times (sc_n-sc_j)+st_i\times (sc_i-sc_j)$</p><p>再把括号拆了:</p><p>$dp_i=dp_j+S\times sc_n-S\times sc_j+st_i\times sc_i-st_i\times sc_j$</p><p>再移项,把 $dp_j$ 放在左边,$dp_i$ 放在右边,发现右边只有 $sc_j$ 与 $j$ 有关,就把它单独拿出来,剩下的放后面:</p><p>$-dp_j=(-S-st_i)\times sc_j-dp_i+S\times sc_n+st_i\times sc_i$</p><p>最后把负号去掉,就得到了我们需要的式子:</p><p>$dp_j=(S+st_i)\times sc_j+dp_i-S\times sc_n-st_i\times sc_i$</p><p>这个式子有啥用呢?如果我们把 $sc_j$ 看成自变量($x$),$dp_j$ 看成因变量($y$),就会发现这个式子,它是个一次函数:</p><script type="math/tex; mode=display">\begin{cases}y=dp_j\\k=S+st_i\\x=sc_j\\b=dp_i-S\times sc_n-st_i\times sc_i\end{cases}</script><p>对于 2.0 版本的 DP 来说,$dp_i$ 的状态由 $dp_j$ 转移而来,所以在确定 $j$ 之前 $dp_i$ 的值都是不确定的。而斜率优化的时候外层循环变量是 $i$,也就意味着此时 $i$ 确定了但 $j$ 没有确定,所以 $k$ 就定下来了,$b$ 中除了 $dp_i$ 之外也都定下来了,这时我们只需要找到使得 $b$ 最小的 $j$,$dp_i$ 也就取到了最小值。</p><p>那什么时候 $b$ 取到最小值呢?利用数形结合,我们可以以 $j$ 为横坐标,$dp_j$ 为纵坐标,把横坐标相差 $1$ 的点两两相连,画出一个图形:</p><p><img src="https://pic.imgdb.cn/item/62b674d50947543129d4a8a3.png" alt="" title="大概是长这个样子"></p><blockquote><p><strong>Ps. 为了方便操作,这张图里两个点之间横坐标不一定相差为 $\bf{1}$,但是真实情况每两个点之间横坐标相差为 $\bf{1}$。</strong></p></blockquote><p>这个时候“引入”里面的东西就派上了用场:因为我们要求 $dp_i$ 也就是 $b$ 的最小值,我们只需要从 $b=0$ 开始,把这个一次函数往上移,直到这个函数第一次碰到某一个点为止,这个点就是我们要找的 $j$。</p><p>那么,这个点该怎么求呢?</p><p>首先有一些点,一看就不可能成为候选,如图:</p><p><img src="https://pic.imgdb.cn/item/62aeba0009475431292c3be7.png" alt="" title="比如说这样的"></p><p>怎么判断这样的点呢?首先看到点 $3$ 和点 $5$,这两个点的情况比较好分析。就拿点 $3$ 来说,很明显发现 $k_b>k_c$,也就是说这个点“凹下去了”,在函数平移的时候会被旁边“凸起来的”点“挡住”。点 $5$ 同理。</p><p>而对于点 $4$,虽然 $k_c<k_d$,但当点 $3$ 和点 $5$ 淘汰之后,把 $(2,4)$ 和 $(4,6)$ 连起来就会发现:</p><p>$k_{(2,4)}>k_{(4,6)}$,所以点 $4$ 也没了。</p><p>在程序中,显然不能用这种方式来找,而是用<strong>每次加入新点时往前逐个淘汰</strong>的方式。使用<strong>单调队列</strong>存点集,从队头到队尾点的横坐标依次增大。每一次 $dp_i$ 算出来之后也要作为新的点加进去,那在加进去之前就在队尾判断,如果把点 $i$ 加进去之后队尾这个点会被淘汰,就把这个点从队尾弹出去,直到队尾符合要求或是队列里没有点了,再把点 $i$ 加进去。</p><p>就这样,我们一边加点一边淘汰,导致每一次找 $j$ 的时候图形都是长这样的:</p><p><img src="https://pic.imgdb.cn/item/62aeba0009475431292c3c0b.png" alt="" title="凸包"></p><p>这个图形中每一个顶点都是凸出来的,所以这玩意儿叫做凸包。如果它是往下凸的就叫下凸包,如果是往上凸的就叫上凸包。</p><p>所以说了半天,这些凸出来的点到底哪一个才是 $j$?其实对于 $j$ 有一个规律:就是以 $j$ 为右端点的那条线段斜率小于 $k$,而以它为左端点的那条线段斜率大于等于 $k$。</p><p>就 3.0 版本数据而言,每一次 $k$ 都不会比上一次小,那么如果前面找到有一条线段的斜率小于当时的 $k$,那在后面,它的斜率也不会比 $k$ 大。对于这种线段我们可以直接把它的左端点从队头弹出单调队列。每一次寻找 $j$ 之前就把这类点弹了,那么此时单调队列的队头就是 $j$。</p><p>最后用 $i$ 和 $j$ 状态转移即可。</p><p>代码:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> ll long long</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>)<span class="number">1e4</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, s, t[maxn], c[maxn];</span><br><span class="line">ll dp[maxn], st[maxn], sc[maxn];</span><br><span class="line"><span class="type">int</span> L, R, q[maxn];</span><br><span class="line"></span><br><span class="line"><span class="comment">// y = kx + b</span></span><br><span class="line"><span class="function"><span class="keyword">inline</span> ll <span class="title">y</span><span class="params">(<span class="type">int</span> i)</span> </span>{ <span class="keyword">return</span> dp[i]; }</span><br><span class="line"><span class="function"><span class="keyword">inline</span> ll <span class="title">k</span><span class="params">(<span class="type">int</span> i)</span> </span>{ <span class="keyword">return</span> s + st[i]; }</span><br><span class="line"><span class="function"><span class="keyword">inline</span> ll <span class="title">x</span><span class="params">(<span class="type">int</span> i)</span> </span>{ <span class="keyword">return</span> sc[i]; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &n, &s);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &t[i], &c[i]);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> st[i] = st[i - <span class="number">1</span>] + t[i];</span><br><span class="line"> sc[i] = sc[i - <span class="number">1</span>] + c[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> <span class="keyword">while</span>(L < R && (<span class="built_in">y</span>(q[L + <span class="number">1</span>]) - <span class="built_in">y</span>(q[L])) < (<span class="built_in">x</span>(q[L + <span class="number">1</span>]) - <span class="built_in">x</span>(q[L])) * <span class="built_in">k</span>(i))</span><br><span class="line"> ++L;</span><br><span class="line"> dp[i] = dp[q[L]] + st[i] * (sc[i] - sc[q[L]]) + s * (sc[n] - sc[q[L]]);</span><br><span class="line"> <span class="keyword">while</span>(L < R && (<span class="built_in">y</span>(i) - <span class="built_in">y</span>(q[R])) * (<span class="built_in">x</span>(q[R]) - <span class="built_in">x</span>(q[R - <span class="number">1</span>])) <= (<span class="built_in">y</span>(q[R]) - <span class="built_in">y</span>(q[R - <span class="number">1</span>])) * (<span class="built_in">x</span>(i) - <span class="built_in">x</span>(q[R])))</span><br><span class="line"> --R;</span><br><span class="line"> q[++R] = i;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%lld"</span>, dp[n]);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="4-0-版本"><a href="#4-0-版本" class="headerlink" title="4.0 版本"></a>4.0 版本</h3><blockquote><p>数据范围:除了 $T_i$ 可以为负数之外,数据范围与 3.0 版本相同。</p><p>时间复杂度:$\Theta(n\log n)$</p></blockquote><p><del>虽然但是,完成一个任务的时间可以为负数确实挺离谱的。</del></p><p>斜率可以是负数带来了一个问题,就是我们不能在用左端点淘汰的方式直接找 $i$ 了。</p><p>为啥呢?因为左端点淘汰有一个条件,就是因为被淘汰的点回不来,所以每一次 $k$ 都不能比上一次小。$T_i>0$ 时 $st$ 肯定是递增的,但是现在不一定了,这也就意味着 $k$ 可能会变小,那对于之前因为所在线段斜率小于当时的 $k$ 而被淘汰的点,但是这条线段的斜率大于现在的这个 $k$,那这个点是不是还要回来?这个很明显就乱套了。</p><p>不过我们还有其它的方法。</p><p>因为就算斜率可以是负数,$k$ 的单调性没了,但凸包单调性依然存在。所以一种时间复杂度劣一点,但是适用于负数的方法出现了——二分。</p><p>二分查找第一个斜率大于 $k$ 的线段,它的左端点就是 $i$。</p><p>代码:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> ll long long</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>)<span class="number">3e5</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, s, t[maxn], c[maxn], st[maxn], sc[maxn];</span><br><span class="line">ll dp[maxn];</span><br><span class="line"><span class="type">int</span> L, R, q[maxn];</span><br><span class="line"></span><br><span class="line"><span class="comment">// y = kx + b</span></span><br><span class="line"><span class="function"><span class="keyword">inline</span> ll <span class="title">y</span><span class="params">(<span class="type">int</span> i)</span> </span>{ <span class="keyword">return</span> dp[i]; }</span><br><span class="line"><span class="function"><span class="keyword">inline</span> ll <span class="title">k</span><span class="params">(<span class="type">int</span> i)</span> </span>{ <span class="keyword">return</span> s + st[i]; }</span><br><span class="line"><span class="function"><span class="keyword">inline</span> ll <span class="title">x</span><span class="params">(<span class="type">int</span> i)</span> </span>{ <span class="keyword">return</span> sc[i]; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">f</span><span class="params">(<span class="type">int</span> l, <span class="type">int</span> r, <span class="type">int</span> i)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(l == r)</span><br><span class="line"> <span class="keyword">return</span> l;</span><br><span class="line"> <span class="type">int</span> mid = (l + r) >> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span>(<span class="built_in">y</span>(q[mid + <span class="number">1</span>]) - <span class="built_in">y</span>(q[mid]) < (<span class="built_in">x</span>(q[mid + <span class="number">1</span>]) - <span class="built_in">x</span>(q[mid])) * i)</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">f</span>(mid + <span class="number">1</span>, r, i);</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">f</span>(l, mid, i);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &n, &s);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &t[i], &c[i]);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> st[i] = st[i - <span class="number">1</span>] + t[i];</span><br><span class="line"> sc[i] = sc[i - <span class="number">1</span>] + c[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="type">int</span> j;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> j = q[<span class="built_in">f</span>(L, R, <span class="built_in">k</span>(i))];</span><br><span class="line"> dp[i] = dp[j] + st[i] * <span class="number">1ll</span> * (sc[i] - sc[j]) + s * <span class="number">1ll</span> * (sc[n] - sc[j]);</span><br><span class="line"> <span class="keyword">while</span>(L < R && (<span class="built_in">y</span>(i) - <span class="built_in">y</span>(q[R])) * (<span class="built_in">x</span>(q[R]) - <span class="built_in">x</span>(q[R - <span class="number">1</span>])) <= (<span class="built_in">y</span>(q[R]) - <span class="built_in">y</span>(q[R - <span class="number">1</span>])) * (<span class="built_in">x</span>(i) - <span class="built_in">x</span>(q[R])))</span><br><span class="line"> --R;</span><br><span class="line"> q[++R] = i;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%lld"</span>, dp[n]);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Ps. 注意精度的问题,计算斜率的除法需要转换为乘法。</p><p>斜率优化大概就是 3.0 版本那个样子,4.0 是对斜率优化普适性的一种优化。</p><hr><h2 id="例题二-1"><a href="#例题二-1" class="headerlink" title="例题二"></a>例题二</h2><p><a href="https://www.luogu.com.cn/problem/P4072">「SDOI2016」征途</a></p><p><del>我和 XSC062 研究这道题研究了半天,最后发现 mjl 和 gm 讲斜优完全讲的是两个东西。</del></p><p>首先是前置工作:</p><p>$<br>p=\dfrac{a_1+a_2+\ldots+a_m}{m}<br>\<br>v=\dfrac{(a_1-p)^2+(a_2-p)^2+\ldots+(a_m-p)^2}{m}<br>$</p><script type="math/tex; mode=display">\begin{aligned}v\times m^2&=m\times\Big((a_1-p)^2+(a_2-p)^2+\ldots+(a_m-p)^2\Big)\\&=m\times\Big(a_1^2+p^2-2\times a_1\times p+a_2^2+p^2-2\times a_2\times p+\ldots+a_m^2+p^2-2\times a_m\times p\Big)\\&=m\times\Big((a_1^2+a_2^2+\ldots+a_m^2)+m\times p^2-2\times p\times (\sum\limits_{i=1}^m a_i)\Big)\\&=m\times\Big((a_1^2+a_2^2+\ldots+a_m^2)+m\times (\frac{\sum_{i=1}^m a_i}{m})^2-2\times (\frac{\sum_{i=1}^m a_i}{m})\times (\sum\limits_{i=1}^m a_i)\Big)\\&=m\times(a_1^2+a_2^2+\ldots+a_m^2)+(\sum\limits_{i=1}^m a_i)^2-2\times(\sum\limits_{i=1}^m a_i)^2\\&=m\times(a_1^2+a_2^2+\ldots+a_m^2)-(\sum\limits_{i=1}^m a_i)^2\end{aligned}</script><p>$(\sum\limits_{i=1}^m a_i)^2$ 是个常数,所以 $dp$ 应该求的是 $m\times(a_1^2+a_2^2+\ldots+a_m^2)$ 的最小值。</p><p>设 $dp_{i,j}$ 为走了 $i$ 天之后,走了 $j$ 段的最小的那个值。状态转移的时候再套一层 $k$,表示第 $i$ 天走了 $k+1\sim j$ 这些路段。</p><p>很容易可以得到状态转移方程($sum$ 数组是 $a$ 的前缀和):</p><script type="math/tex; mode=display">\begin{aligned}dp_{i,j}&=\min\{dp_{i,j},dp_{i-1,k}+(sum_j-sum_k)^2\}\\(ans&=m\times dp_{m,n}-sum_n^2)\end{aligned}</script><p>好了,接下来就是重头戏:怎么斜率优化?</p><p>首先要确定这三个循环变量哪一个作为自变量 $x$,这不是随便选的,观察一下这个状态转移方程就会发现有一个 $(sum_j-sum_k)^2$ 展开之后是 $sum_j^2+sum_k^2-2\times sum_j\times sum_k$,这个东西比较难处理,不过有一个 $2\times sum_j\times sum_k$ 作为切入点,所以我们选择 $k$ 作为自变量 $x$,这样 $2\times sum_j$ 就作为斜率 $k$,$sum_j^2$ 就作为 $b$ 的一部分,比较难处理的 $sum_k^2$ 就挪到等号左边作为 $y$ 的一部分。因为斜率优化之后也要枚举自变量的值,所以说 $sum_k^2$ 不会影响最后的结果。</p><script type="math/tex; mode=display">\begin{aligned}dp_{i,j}&=\min\{dp_{i-1,k}+(sum_j-sum_k)^2\}\\&=dp_{i-1,k}+(sum_j-sum_k)^2\\&=dp_{i-1,k}+sum_j^2+sum_k^2-2\times sum_j\times sum_k\\-dp_{i-1,k}-sum_k^2&=(-2\times sum_j)\times sum_k+(sum_j^2-dp_{i,j})\\dp_{i-1,k}+sum_k^2&=(2\times sum_j)\times sum_k+(dp_{i,j}-sum_j^2)\end{aligned}</script><script type="math/tex; mode=display">\begin{cases}y=dp_{i-1,k}+sum_k^2\\k=2\times sum_j\\x=sum_k\\b=dp_{i,j}-sum_j^2\end{cases}</script><p>由于是求最小值,所以维护下凸包。然后就是板子了。</p>]]></content>
<summary type="html">难死我了 qwq</summary>
<category term="学习笔记" scheme="https://blog.liynw.top/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<category term="动态规划" scheme="https://blog.liynw.top/tags/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/"/>
</entry>
<entry>
<title>AFO 随心记</title>
<link href="https://blog.liynw.top/posts/9bb15805/"/>
<id>https://blog.liynw.top/posts/9bb15805/</id>
<published>2022-07-10T19:59:14.000Z</published>
<updated>2022-07-10T19:59:14.000Z</updated>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>笔者坐标 CQ,准初三,曾经是一位 OIer。</p><p>我是 2022/06/22 退役的。至于为啥这篇文章现在开写,一是当时快要期末考试了,没时间写,<del>二是我确实很懒</del>,所以就一直鸽到了现在(x。</p><p>AFO 是什么意思呢,就是 “Away from OI”,也就是指退竞赛。其实我在初一那个暑假就已经犹豫该不该继续学了,当时还是坚持了下来(我们这一届学 OI 的人很少,没什么淘汰),结果学了一年还是觉得 OI 太难了,就退了……</p><p>实话实说吧,我学 OI 基本上也就是瞎搞居多,没有特别用心,所以成绩不好也是必然的😓。</p><p>五大竞赛里面 OI 一直属于人比较少的,毕竟很多家长觉得信息又不是中高考科目,如果没有拿牌学了也没用,而别的竞赛至少可以提前学高中内容,对于以后的学习还有一点帮助。但是学这一年真的对我来说没有任何影响吗?我觉得不是的。</p><hr><h2 id="聊一聊自己的-OI-生涯"><a href="#聊一聊自己的-OI-生涯" class="headerlink" title="聊一聊自己的 OI 生涯"></a>聊一聊自己的 OI 生涯</h2><p>流水账,太长可以不看。</p><h3 id="初中之前"><a href="#初中之前" class="headerlink" title="初中之前"></a>初中之前</h3><p>最初接触编程,是小学三年级的时候学编程猫,那玩意儿很简单,就是拼积木,我基本上每次都能提前完成老师布置的任务,于是瞎搞就成了家常便饭。我个人觉得我对于编程的兴趣就是从那个时候开始的。</p><p>六年级的时候,由于我小升初上岸,我妈说要给我抱一个我喜欢的兴趣班,让我在画画和编程里面选一个。我思考了一下,还是学了编程,当时的心思也很简单,那时我刚听说互联网上面的东西都是用代码一行一行敲出来的,觉得特别神奇,觉得那些把互联网编出来的人好强,我也想像他们一样。<del>现在看来这个想法实在是太天真了 qwq</del></p><p>结果我妈被一个【】机构给坑了,不到一年花了几大万,结果教学质量极差,而且内容基本上和初中那边教的信息课内容是一样的,早知道就不学了……<del>说这一年经历有什么用呢,就是让一个小学六年级的女生体会到了自己在信息课上暴切初高中生的感觉 Zzz……</del></p><p>时间很快就到了暑假,初中那边让每个人填所谓“竞赛志愿”,我本来不想写的,但是我看了一下基本上我们班每个人都写了,而且第一志愿和第二志愿都写了,而且我跟我妈打电话的时候她说让我去试一下,“你填了也不一定选得上”,于是我想了很久,第一志愿填了信息,把第二志愿空着……</p><p>结果呢?尽管我在初中那边表现不好,但还是很神奇地成功选上了。</p><hr><h3 id="第一次参加比赛"><a href="#第一次参加比赛" class="headerlink" title="第一次参加比赛"></a>第一次参加比赛</h3><p>初一上册还没有分科,所以五科竞赛都要上。</p><p>2020 年大概是 10 月吧,第一次参加比赛——CSP-J2020 的初赛。反正是一脸懵逼乱蒙了一波,还过了。我们班有一个很强的男生没过初赛,从此他再也不来上信息课了。</p><p>最后我们班进了 6 个人(我,Peter,Paul,小明,lza 和 dpc),二班忘了(人数介于一班和三班之间),三班进的最多,12 个人,还有几个别的班的。40 多个人了中我是唯一的女生。</p><p>之前没写游记,这里浅浅补一下。全凭记忆可能有些不太精确了。</p><p>11 月,去两江南开参加 CSP-J2020 复赛,不得不说 LJNK 是真的高档,操场是标准的 400 米操场,我们去的时候是早上,雾还没完全散,操场从一边看都看不到另一边。<del>总之 Paul 和小明在操场上玩疯了,还是我们带队老师费了好大劲才把他俩叫回来的。</del></p><p>雾散了之后出了太阳,照在建筑物上非常好看。我们在展板那里拍了张合照然后就进了体育馆准备比赛了。</p><p>我走到自己的位置上,把框架敲好,然后等着发卷子。发了卷子之后按照老师的叮嘱,解密看题。</p><p>第一题看起来不难,我想了一会儿之后打了一个循环拆解(PS:那个时候我基本上什么算法都没学),结果没过样例。我非常惊慌,调了大概半个小时才发现我少打了一层循环……加上就过了。(当时才不知道有什么大样例呢,反正过了小样例就是对了 /ll)。</p><p>然后开始做第二题,看起来好像要排序的样子,一看 $n\le 600$……桶排!于是敲了个桶排过了。</p><p>第三题看着好难的样子,赶紧敲个全输出 $0$ 溜了……</p><p>耗时最长的是第四题,那个时候不知道 DP 不知道暴搜只知道贪心,于是花了很长的时间敲了一个非常奇怪的贪心。</p><p><del>全程没动 LJNK 发的三明治。</del></p><p>出来之后和 Peter 友好交流了一下,发现他 T4 也打的贪心。dpc 和 lza 也在交流,Paul 和小明不知道飞哪去了。说了一会儿我们就出校门各找各妈了。</p><p>中午回学校的时候我们几个正好遇到了 wxc(一班班主任),被他“截胡”下来说了一会儿,然后就回教室了。结果下午又考生物,没发挥好错了一堆……<del>没关系,满分 150 我们班也就一个人上了 100。</del></p><p>事实上没怎么关心出分吧,只是在成绩公布那一天看了一下自己的成绩:$100+100+5+0=205$。</p><p>又过了几天教练公布分数,一等线是 $205$!<del>这波啊,这波精准卡线了属于是。</del></p><p>我们班最高分 $215$,年级最高分 $245$。<del>有意思的是,这两位后来成为了数竞最强的两个人哦。</del></p><blockquote><p>UPD:在大概 2022年11月的时候,那个考 $245$ 的佬成了我们学校的传奇,因为他一个初三的跟全国和他同级的和高中的去考丘班,考了笔试第一面试第三,于是这个当时刚满14 的人已经被清华录了</p></blockquote><hr><h3 id="填志愿,分科"><a href="#填志愿,分科" class="headerlink" title="填志愿,分科"></a>填志愿,分科</h3><p>大概是在 2021 年 1 月左右,寒假之前。本来我是想选信息的,但是经过这半年我发现我化学比信息好,而且我爹以前是学化竞的……于是我开始纠结了。后来我为什么选了信息呢?第一是因为我最开始进来是写的信息,第二是化学老师的拉人方法让我感到厌恶(都不让我们吃饭 qwq),第三是我觉得当时那些学化竞的人有相当一部分很烦。</p><p>我们这一届选信息的人特别少,三个班将近 180 个人里面只有 19 个人,还有两个是调剂的(就是指两个志愿填的都不是某个科目,但是因为人数不平衡被强制弄过去)。我们班只有三个,我,一个叫 wwh 的女生和上文提到的 Peter 同学。教练看着人这么少,于是只好在编程社拉了一些同学过来学。</p><hr><h3 id="初一"><a href="#初一" class="headerlink" title="初一"></a>初一</h3><p>寒假的时候,开通了自己的第一个博客。<a href="https://www.luogu.com.cn/blog/LingWang-Blog/">Link</a></p><p>寒假基本上在瞎搞,成绩在 70 多个人里面都能算垫底,被教练说过好多次。开学了,看着编程社的同学越退越少,我也开始慌了,就不敢摸鱼了。那个时候应该是我竞赛成绩最好的时候,大概排在中等吧。</p><p>这一段时间给我影响比较深的事情就是,我得知了我们隔壁机房有一个很厉害的妹子叫 XSC062,比我小一届,CSP-J2020 和我一样考的 $205$ 分。于是我去翻了翻她的洛谷个人主页,发现她用 Hexo 建了个博客,当时正愁于找不到好的平台写文章的我一下子就有了个大胆的想法。在暑假的时候,我成功把站建了起来(也就是您现在看到的,只不过当时还没那么高大上)。</p><hr><h3 id="初二"><a href="#初二" class="headerlink" title="初二"></a>初二</h3><p>认识了 XSC062,很快和她成了朋友。几乎每次都是我、她和 Peter 一起吃饭,到了那个时候我们都很开心。</p><p>开学没多久,当然按照惯例参加 CSP,只不过我这次只参加了 S 级,结果挂了得了三等奖。</p><div class="tag link"><a class="link-card" title="CSP2021 游记" href="/posts/9ec8265c/"><div class="left"><img src="https://cdn.jsdelivr.net/npm/[email protected]/img/favicon.webp"/></div><div class="right"><p class="text">CSP2021 游记</p><p class="url">/posts/9ec8265c/</p></div></a></div><p>接着是 NOIP,以非正式选手的身份去参赛,又是一个三等(这次是因为能力不够)。</p><div class="tag link"><a class="link-card" title="NOIP2021 爆炸记" href="/posts/407315f9/"><div class="left"><img src="https://cdn.jsdelivr.net/npm/[email protected]/img/favicon.webp"/></div><div class="right"><p class="text">NOIP2021 爆炸记</p><p class="url">/posts/407315f9/</p></div></a></div><p>后面开始学一些比较难的内容比如说树剖什么的,渐渐感觉心有余而力不足了,自己的成绩也在下滑,于是就打算离开了。</p><hr><h2 id="它带给我了什么"><a href="#它带给我了什么" class="headerlink" title="它带给我了什么"></a>它带给我了什么</h2><p>不能说两年 OI 对我什么影响都没有,影响肯定还是很大的,但是是好的还是坏的其实我也说不清楚。</p><p>如果我没有学 OI 的话,那我就不会了解到那么多<del>奇奇怪怪的</del>知识,不会认识那么多有趣的人,更不会接触到 Hexo 这个圈子。我家长认为我不该一天到晚花那么多时间在我的网站上,但是这应该算是我为数不多的兴趣爱好吧,很难想象如果我学了化竞现在会是什么样呢,还要退竞赛吗?</p><p>其实退役我还是有一些不舍的,在机房一起奋斗的时光还是很美好的。尤其是对于 XSC062,她不用社交媒体,我们俩又不在一个年级,也就是说我们以后没有几次见面的机会了。</p><hr><h2 id="要初三了"><a href="#要初三了" class="headerlink" title="要初三了"></a>要初三了</h2><p>想写一点话来勉励自己,却又不知道写什么,只是详列一下自己的目标清单:</p><ul><li><p>[ ] 暑假和初三好好学习,不要像现在这样花这么多时间在折腾网站上,争取初三第一批保送;</p></li><li><p>[ ] 数学稳定上 $140$;</p></li><li><p>[x] 体考半期之前满分;</p></li><li><p>[ ] 中考 $720+$;</p></li><li><p>[ ] 初三的时候多学一点高中的知识,为未来高中铺路。</p></li></ul><p>总之,戒骄戒躁,砥砺前行吧。</p><p>(End)</p>]]></content>
<summary type="html">退役了,有些话想说一说</summary>
<category term="生活" scheme="https://blog.liynw.top/categories/%E7%94%9F%E6%B4%BB/"/>
<category term="闲聊" scheme="https://blog.liynw.top/tags/%E9%97%B2%E8%81%8A/"/>
</entry>
<entry>
<title>butterfly 魔改日记</title>
<link href="https://blog.liynw.top/posts/ad2e3741/"/>
<id>https://blog.liynw.top/posts/ad2e3741/</id>
<published>2022-05-21T09:01:34.000Z</published>
<updated>2022-05-21T09:01:34.000Z</updated>
<content type="html"><![CDATA[<p>本站使用的主题:butterfly 4.2.2</p><h2 id="相关推荐版块侧栏卡片化"><a href="#相关推荐版块侧栏卡片化" class="headerlink" title="相关推荐版块侧栏卡片化"></a>相关推荐版块侧栏卡片化</h2><p>See:<a href="https://akilar.top/posts/194e1534/">https://akilar.top/posts/194e1534/</a></p><p><code>[Blogroot]\themes\butterfly\scripts\helpers\related_post.js</code> 47~71 行</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (relatedPosts.<span class="property">length</span> > <span class="number">0</span>) {</span><br><span class="line"> result += <span class="string">'<div class="card-widget card-recommend-post">'</span></span><br><span class="line"> result += <span class="string">`<div class="item-headline"><i class="fas fa-dharmachakra"></i><span><span class="subst">${headlineLang}</span></span></div>`</span></span><br><span class="line"> result += <span class="string">'<div class="aside-list">'</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i < <span class="title class_">Math</span>.<span class="title function_">min</span>(relatedPosts.<span class="property">length</span>, limitNum); i++) {</span><br><span class="line"> <span class="keyword">const</span> cover =</span><br><span class="line"> relatedPosts[i].<span class="property">cover</span> === <span class="literal">false</span></span><br><span class="line"> ? relatedPosts[i].<span class="property">randomcover</span></span><br><span class="line"> : relatedPosts[i].<span class="property">cover</span></span><br><span class="line"> result += <span class="string">`<div class="aside-list-item">`</span></span><br><span class="line"> result += <span class="string">`<a class="thumbnail" href="<span class="subst">${<span class="variable language_">this</span>.url_for(relatedPosts[i].path)}</span>" title="<span class="subst">${relatedPosts[i].title}</span>"><img src="<span class="subst">${<span class="variable language_">this</span>.url_for(cover)}</span>" alt="<span class="subst">${relatedPosts[i].title}</span>"></a>`</span></span><br><span class="line"> result += <span class="string">`<div class="content">`</span></span><br><span class="line"> result += <span class="string">`<a class="title" href="<span class="subst">${<span class="variable language_">this</span>.url_for(relatedPosts[i].path)}</span>" title="<span class="subst">${relatedPosts[i].title}</span>"><span class="subst">${relatedPosts[i].title}</span></a>`</span></span><br><span class="line"> <span class="keyword">if</span> (dateType === <span class="string">'created'</span>) {</span><br><span class="line"> result += <span class="string">`<time datetime="<span class="subst">${<span class="variable language_">this</span>.date(relatedPosts[i].created, hexoConfig.date_format)}</span>" title="发表于 <span class="subst">${<span class="variable language_">this</span>.date(relatedPosts[i].created, hexoConfig.date_format)}</span>"><span class="subst">${<span class="variable language_">this</span>.date(relatedPosts[i].created, hexoConfig.date_format)}</span></time>`</span></span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> result += <span class="string">`<time datetime="<span class="subst">${<span class="variable language_">this</span>.date(relatedPosts[i].updated, hexoConfig.date_format)}</span>" title="发表于 <span class="subst">${<span class="variable language_">this</span>.date(relatedPosts[i].updated, hexoConfig.date_format)}</span>"><span class="subst">${<span class="variable language_">this</span>.date(relatedPosts[i].updated, hexoConfig.date_format)}</span></time>`</span></span><br><span class="line"> }</span><br><span class="line"> result += <span class="string">`</div></div>`</span></span><br><span class="line"> }</span><br><span class="line"> result += <span class="string">'</div></div>'</span></span><br><span class="line"> <span class="keyword">return</span> result</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p><code>[Blogroot]\themes\butterfly\layout\post.pug</code> 26~27 行</p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"> if theme.post_pagination</span><br><span class="line"> include includes/pagination.pug</span><br><span class="line"><span class="deletion">- if theme.related_post && theme.related_post.enable</span></span><br><span class="line"><span class="deletion">- != related_posts(page,site.posts)</span></span><br><span class="line"></span><br><span class="line"> if page.comments !== false && theme.comments && theme.comments.use</span><br></pre></td></tr></table></figure><p><code>[Blogroot]\themes\butterfly\layout\includes\widget\index.pug</code> 16~17 行</p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">#aside-content.aside-content</span><br><span class="line"> //- post</span><br><span class="line"> if is_post()</span><br><span class="line"> if showToc && theme.toc.style_simple</span><br><span class="line"> .sticky_layout</span><br><span class="line"> include ./card_post_toc.pug</span><br><span class="line"> else</span><br><span class="line"> !=partial('includes/custom/SAO_card_player', {}, {cache:true})</span><br><span class="line"> !=partial('includes/widget/card_announcement', {}, {cache:true})</span><br><span class="line"> !=partial('includes/widget/card_top_self', {}, {cache:true}) </span><br><span class="line"> .sticky_layout</span><br><span class="line"> if showToc</span><br><span class="line"> include ./card_post_toc.pug</span><br><span class="line"><span class="addition">+ if theme.related_post && theme.related_post.enable</span></span><br><span class="line"><span class="addition">+ != related_posts(page,site.posts)</span></span><br><span class="line"><span class="deletion">- - !=partial('includes/widget/card_recent_post', {}, {cache:true})</span></span><br><span class="line"> !=partial('includes/widget/card_ad', {}, {cache:true})</span><br></pre></td></tr></table></figure><hr><h2 id="修改加载动画内容"><a href="#修改加载动画内容" class="headerlink" title="修改加载动画内容"></a>修改加载动画内容</h2><p>See:<a href="https://akilar.top/posts/3d221bf2/">https://akilar.top/posts/3d221bf2/</a></p><p><code>[Blogroot]\themes\butterfly\layout\includes\loading\loading.pug</code> 全部</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">if theme.preloader.enable</span><br><span class="line"> case theme.preloader.load_style </span><br><span class="line"> when 'gear'</span><br><span class="line"> include ./load_style/gear.pug</span><br></pre></td></tr></table></figure><p>新建 <code>[Blogroot]\themes\butterfly\layout\includes\loading\load_style\gear.pug</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">#loading-box</span><br><span class="line"> .gear-loader</span><br><span class="line"> .gear-loader_overlay</span><br><span class="line"> .gear-loader_cogs</span><br><span class="line"> .gear-loader_cogs__top</span><br><span class="line"> .gear-top_part</span><br><span class="line"> .gear-top_part</span><br><span class="line"> .gear-top_part</span><br><span class="line"> .gear-top_hole</span><br><span class="line"> .gear-loader_cogs__left</span><br><span class="line"> .gear-left_part</span><br><span class="line"> .gear-left_part</span><br><span class="line"> .gear-left_part</span><br><span class="line"> .gear-left_hole</span><br><span class="line"> .gear-loader_cogs__bottom</span><br><span class="line"> .gear-bottom_part</span><br><span class="line"> .gear-bottom_part</span><br><span class="line"> .gear-bottom_part</span><br><span class="line"> .gear-bottom_hole</span><br></pre></td></tr></table></figure><p><code>[Blogroot]\themes\butterfly\source\css\_layout\loading.styl</code> 全部</p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> <span class="built_in">hexo-config</span>(<span class="string">'preloader.enable'</span>)</span><br><span class="line"> <span class="keyword">if</span> <span class="built_in">hexo-config</span>(<span class="string">'preloader.load_style'</span>) == <span class="string">'gear'</span></span><br><span class="line"> <span class="keyword">@import</span> <span class="string">'./_load_style/gear'</span></span><br></pre></td></tr></table></figure><p>新建 <code>[Blogroot]\themes\butterfly\source\css\_load_style\gear.styl</code></p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-id">#loading-box</span></span><br><span class="line"> <span class="attribute">position</span> fixed</span><br><span class="line"> <span class="attribute">z-index</span> <span class="number">1000</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">100vw</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">100vh</span></span><br><span class="line"> <span class="attribute">overflow</span> hidden</span><br><span class="line"> <span class="attribute">text-align</span> center</span><br><span class="line"> &<span class="selector-class">.loaded</span></span><br><span class="line"> <span class="attribute">z-index</span> -<span class="number">1000</span></span><br><span class="line"> <span class="selector-class">.gear-loader</span></span><br><span class="line"> <span class="attribute">display</span> none</span><br><span class="line"> <span class="selector-class">.gear-loader</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">100%</span></span><br><span class="line"> <span class="attribute">position</span> relative</span><br><span class="line"> <span class="attribute">margin</span> auto</span><br><span class="line"> <span class="attribute">width</span> <span class="number">400px</span></span><br><span class="line"> <span class="selector-class">.gear-loader_overlay</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">150px</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">150px</span></span><br><span class="line"> <span class="attribute">background</span> transparent</span><br><span class="line"> <span class="attribute">box-shadow</span> <span class="number">0px</span> <span class="number">0px</span> <span class="number">0px</span> <span class="number">1000px</span> <span class="built_in">rgba</span>(<span class="number">255</span>, <span class="number">255</span>, <span class="number">255</span>, <span class="number">0.67</span>), <span class="number">0px</span> <span class="number">0px</span> <span class="number">19px</span> <span class="number">0px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.16</span>) inset</span><br><span class="line"> <span class="attribute">border-radius</span> <span class="number">100%</span></span><br><span class="line"> <span class="attribute">z-index</span> -<span class="number">1</span></span><br><span class="line"> <span class="attribute">position</span> absolute</span><br><span class="line"> <span class="attribute">left</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">right</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">top</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">bottom</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">margin</span> auto</span><br><span class="line"> <span class="selector-class">.gear-loader_cogs</span></span><br><span class="line"> <span class="attribute">z-index</span> -<span class="number">2</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">100px</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">100px</span></span><br><span class="line"> <span class="attribute">top</span> -<span class="number">120px</span> <span class="meta">!important</span></span><br><span class="line"> <span class="attribute">position</span> absolute</span><br><span class="line"> <span class="attribute">left</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">right</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">top</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">bottom</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">margin</span> auto</span><br><span class="line"> <span class="selector-class">.gear-loader_cogs__top</span></span><br><span class="line"> <span class="attribute">position</span> relative</span><br><span class="line"> <span class="attribute">width</span> <span class="number">100px</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">100px</span></span><br><span class="line"> <span class="attribute">transform-origin</span> <span class="number">50px</span> <span class="number">50px</span></span><br><span class="line"> -webkit-<span class="attribute">animation</span> rotate <span class="number">10s</span> infinite linear</span><br><span class="line"> <span class="attribute">animation</span> rotate <span class="number">10s</span> infinite linear</span><br><span class="line"> <span class="selector-tag">div</span></span><br><span class="line"> <span class="selector-pseudo">&:nth-of-type</span>(<span class="number">1</span>)</span><br><span class="line"> <span class="attribute">transform</span> <span class="built_in">rotate</span>(<span class="number">30deg</span>)</span><br><span class="line"> <span class="selector-pseudo">&:nth-of-type</span>(<span class="number">2</span>)</span><br><span class="line"> <span class="attribute">transform</span> <span class="built_in">rotate</span>(<span class="number">60deg</span>)</span><br><span class="line"> <span class="selector-pseudo">&:nth-of-type</span>(<span class="number">3</span>)</span><br><span class="line"> <span class="attribute">transform</span> <span class="built_in">rotate</span>(<span class="number">90deg</span>)</span><br><span class="line"> &<span class="selector-class">.gear-top_part</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">100px</span></span><br><span class="line"> <span class="attribute">border-radius</span> <span class="number">10px</span></span><br><span class="line"> <span class="attribute">position</span> absolute</span><br><span class="line"> <span class="attribute">height</span> <span class="number">100px</span></span><br><span class="line"> <span class="attribute">background</span> <span class="number">#f98db9</span></span><br><span class="line"> &<span class="selector-class">.gear-top_hole</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">50px</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">50px</span></span><br><span class="line"> <span class="attribute">border-radius</span> <span class="number">100%</span></span><br><span class="line"> <span class="attribute">background</span> white</span><br><span class="line"> <span class="attribute">position</span> absolute</span><br><span class="line"> <span class="attribute">position</span> absolute</span><br><span class="line"> <span class="attribute">left</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">right</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">top</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">bottom</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">margin</span> auto</span><br><span class="line"> <span class="selector-class">.gear-loader_cogs__left</span></span><br><span class="line"> <span class="attribute">position</span> relative</span><br><span class="line"> <span class="attribute">width</span> <span class="number">80px</span></span><br><span class="line"> <span class="attribute">transform</span> <span class="built_in">rotate</span>(<span class="number">16deg</span>)</span><br><span class="line"> <span class="attribute">top</span> <span class="number">28px</span></span><br><span class="line"> <span class="attribute">transform-origin</span> <span class="number">40px</span> <span class="number">40px</span></span><br><span class="line"> <span class="attribute">animation</span> rotate_left <span class="number">10s</span> <span class="number">0.1s</span> infinite reverse linear</span><br><span class="line"> <span class="attribute">left</span> -<span class="number">24px</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">80px</span></span><br><span class="line"> <span class="selector-tag">div</span></span><br><span class="line"> <span class="selector-pseudo">&:nth-of-type</span>(<span class="number">1</span>)</span><br><span class="line"> <span class="attribute">transform</span> <span class="built_in">rotate</span>(<span class="number">30deg</span>)</span><br><span class="line"> <span class="selector-pseudo">&:nth-of-type</span>(<span class="number">2</span>)</span><br><span class="line"> <span class="attribute">transform</span> <span class="built_in">rotate</span>(<span class="number">60deg</span>)</span><br><span class="line"> <span class="selector-pseudo">&:nth-of-type</span>(<span class="number">3</span>)</span><br><span class="line"> <span class="attribute">transform</span> <span class="built_in">rotate</span>(<span class="number">90deg</span>)</span><br><span class="line"> &<span class="selector-class">.gear-left_part</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">80px</span></span><br><span class="line"> <span class="attribute">border-radius</span> <span class="number">6px</span></span><br><span class="line"> <span class="attribute">position</span> absolute</span><br><span class="line"> <span class="attribute">height</span> <span class="number">80px</span></span><br><span class="line"> <span class="attribute">background</span> <span class="number">#97ddff</span></span><br><span class="line"> &<span class="selector-class">.gear-left_hole</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">40px</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">40px</span></span><br><span class="line"> <span class="attribute">border-radius</span> <span class="number">100%</span></span><br><span class="line"> <span class="attribute">background</span> white</span><br><span class="line"> <span class="attribute">position</span> absolute</span><br><span class="line"> <span class="attribute">position</span> absolute</span><br><span class="line"> <span class="attribute">left</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">right</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">top</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">bottom</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">margin</span> auto</span><br><span class="line"> <span class="selector-class">.gear-loader_cogs__bottom</span></span><br><span class="line"> <span class="attribute">position</span> relative</span><br><span class="line"> <span class="attribute">width</span> <span class="number">60px</span></span><br><span class="line"> <span class="attribute">top</span> -<span class="number">65px</span></span><br><span class="line"> <span class="attribute">transform-origin</span> <span class="number">30px</span> <span class="number">30px</span></span><br><span class="line"> -webkit-<span class="attribute">animation</span> rotate_left <span class="number">10.2s</span> <span class="number">0.4s</span> infinite linear</span><br><span class="line"> <span class="attribute">animation</span> rotate_left <span class="number">10.2s</span> <span class="number">0.4s</span> infinite linear</span><br><span class="line"> <span class="attribute">transform</span> <span class="built_in">rotate</span>(<span class="number">4deg</span>)</span><br><span class="line"> <span class="attribute">left</span> <span class="number">79px</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">60px</span></span><br><span class="line"> <span class="selector-tag">div</span></span><br><span class="line"> <span class="selector-pseudo">&:nth-of-type</span>(<span class="number">1</span>)</span><br><span class="line"> <span class="attribute">transform</span> <span class="built_in">rotate</span>(<span class="number">30deg</span>)</span><br><span class="line"> <span class="selector-pseudo">&:nth-of-type</span>(<span class="number">2</span>)</span><br><span class="line"> <span class="attribute">transform</span> <span class="built_in">rotate</span>(<span class="number">60deg</span>)</span><br><span class="line"> <span class="selector-pseudo">&:nth-of-type</span>(<span class="number">3</span>)</span><br><span class="line"> <span class="attribute">transform</span> <span class="built_in">rotate</span>(<span class="number">90deg</span>)</span><br><span class="line"> &<span class="selector-class">.gear-bottom_part</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">60px</span></span><br><span class="line"> <span class="attribute">border-radius</span> <span class="number">5px</span></span><br><span class="line"> <span class="attribute">position</span> absolute</span><br><span class="line"> <span class="attribute">height</span> <span class="number">60px</span></span><br><span class="line"> <span class="attribute">background</span> <span class="number">#ffcd66</span></span><br><span class="line"> &<span class="selector-class">.gear-bottom_hole</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">30px</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">30px</span></span><br><span class="line"> <span class="attribute">border-radius</span> <span class="number">100%</span></span><br><span class="line"> <span class="attribute">background</span> white</span><br><span class="line"> <span class="attribute">position</span> absolute</span><br><span class="line"> <span class="attribute">position</span> absolute</span><br><span class="line"> <span class="attribute">left</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">right</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">top</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">bottom</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">margin</span> auto</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/* Animations */</span></span><br><span class="line"><span class="keyword">@-webkit-keyframes</span> rotate {</span><br><span class="line"> from {</span><br><span class="line"> <span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">0deg</span>);</span><br><span class="line"> }</span><br><span class="line"> to {</span><br><span class="line"> <span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">360deg</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="keyword">@keyframes</span> rotate {</span><br><span class="line"> from {</span><br><span class="line"> <span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">0deg</span>);</span><br><span class="line"> }</span><br><span class="line"> to {</span><br><span class="line"> <span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">360deg</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="keyword">@-webkit-keyframes</span> rotate_left {</span><br><span class="line"> from {</span><br><span class="line"> <span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">16deg</span>);</span><br><span class="line"> }</span><br><span class="line"> to {</span><br><span class="line"> <span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">376deg</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="keyword">@keyframes</span> rotate_left {</span><br><span class="line"> from {</span><br><span class="line"> <span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">16deg</span>);</span><br><span class="line"> }</span><br><span class="line"> to {</span><br><span class="line"> <span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">376deg</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="keyword">@-webkit-keyframes</span> rotate_right {</span><br><span class="line"> from {</span><br><span class="line"> <span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">4deg</span>);</span><br><span class="line"> }</span><br><span class="line"> to {</span><br><span class="line"> <span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">364deg</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="keyword">@keyframes</span> rotate_right {</span><br><span class="line"> from {</span><br><span class="line"> <span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">4deg</span>);</span><br><span class="line"> }</span><br><span class="line"> to {</span><br><span class="line"> <span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">364deg</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><code>[Blogroot]\themes\butterfly\layout\includes\layout.pug</code> 11 行</p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"> body</span><br><span class="line"><span class="deletion">- if theme.preloader</span></span><br><span class="line"><span class="addition">+ if theme.preloader.enable</span></span><br><span class="line"> !=partial('includes/loading/loading', {}, {cache: true})</span><br></pre></td></tr></table></figure><p><code>[Blogroot]\themes\butterfly\source\css\var.styl</code> 101 行</p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"> // preloader</span><br><span class="line"><span class="deletion">- $preloader-bg = #37474f</span></span><br><span class="line"><span class="addition">+ $preloader-bg = hexo-config('preloader.enable') && hexo-config('preloader.load_color') ? convert(hexo-config('preloader.load_color')) : #37474f</span></span><br><span class="line"> $preloader-word-color = #fff</span><br></pre></td></tr></table></figure><p><code>[Blogroot]\themes\butterfly\layout\includes\loading\loading-js.pug</code> 全部</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">script</span>(<span class="keyword">async</span>).</span><br><span class="line"> <span class="keyword">var</span> preloader = {</span><br><span class="line"> <span class="attr">endLoading</span>: <span class="function">() =></span> {</span><br><span class="line"> <span class="variable language_">document</span>.<span class="property">body</span>.<span class="property">style</span>.<span class="property">overflow</span> = <span class="string">'auto'</span>;</span><br><span class="line"> <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">'loading-box'</span>).<span class="property">classList</span>.<span class="title function_">add</span>(<span class="string">"loaded"</span>)</span><br><span class="line"> },</span><br><span class="line"> <span class="attr">initLoading</span>: <span class="function">() =></span> {</span><br><span class="line"> <span class="variable language_">document</span>.<span class="property">body</span>.<span class="property">style</span>.<span class="property">overflow</span> = <span class="string">''</span>;</span><br><span class="line"> <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">'loading-box'</span>).<span class="property">classList</span>.<span class="title function_">remove</span>(<span class="string">"loaded"</span>)</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">'load'</span>,preloader.<span class="title function_">endLoading</span>())</span><br><span class="line"> <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">'loading-box'</span>).<span class="title function_">addEventListener</span>(<span class="string">'click'</span>,<span class="function">()=></span> {preloader.<span class="title function_">endLoading</span>()})</span><br></pre></td></tr></table></figure><hr><h2 id="友链样式魔改"><a href="#友链样式魔改" class="headerlink" title="友链样式魔改"></a>友链样式魔改</h2><p>See:<a href="https://akilar.top/posts/57291286/">https://akilar.top/posts/57291286/</a></p><p><code>[Blogroot]\themes\butterfly\layout\includes\page\flink.pug</code> 全部</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">case theme.flink_style</span><br><span class="line"> when 'flexcard'</span><br><span class="line"> include ./flink_style/flexcard.pug</span><br></pre></td></tr></table></figure><p>新建 <code>[Blogroot]\themes\butterfly\layout\includes\page\flink_style\flexcard.pug</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">#article-container</span><br><span class="line"> if top_img === false</span><br><span class="line"> h1.page-title= page.title</span><br><span class="line"> .flink</span><br><span class="line"> if site.data.link</span><br><span class="line"> each i in site.data.link</span><br><span class="line"> if i.class_name</span><br><span class="line"> h2!= i.class_name</span><br><span class="line"> if i.class_desc</span><br><span class="line"> .flink-desc!=i.class_desc</span><br><span class="line"> .flink-list</span><br><span class="line"> each item in i.link_list</span><br><span class="line"> a.flink-list-card(href=url_for(item.link) target='_blank' data-title=item.descr)</span><br><span class="line"> .wrapper.cover</span><br><span class="line"> - var siteshot = item.siteshot ? url_for(item.siteshot) : 'https://image.thum.io/get/width/400/crop/800/allowJPG/wait/20/noanimate/' + item.link</span><br><span class="line"> img.no-lightbox.cover.fadeIn(src=siteshot onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.post_page) + `'` alt='' ) </span><br><span class="line"> .info</span><br><span class="line"> img.no-lightbox(src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt='' )</span><br><span class="line"> span.flink-sitename= item.name</span><br><span class="line"> != page.content</span><br></pre></td></tr></table></figure><p><code>[Blogroot]\themes\butterfly\source\css\_page\flink.styl</code> 全部</p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> <span class="built_in">hexo-config</span>(<span class="string">'flink_style'</span>) == <span class="string">'flexcard'</span></span><br><span class="line"> <span class="keyword">@import</span> <span class="string">'./_flink_style/flexcard'</span></span><br></pre></td></tr></table></figure><p>新建 <code>[Blogroot]\themes\butterfly\source\css\_flink_style\flexcard.styl</code></p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.flink-list</span></span><br><span class="line"> <span class="attribute">overflow</span> auto</span><br><span class="line"> & > <span class="selector-tag">a</span></span><br><span class="line"> <span class="attribute">width</span> <span class="built_in">calc</span>(<span class="number">25%</span> - <span class="number">15px</span>)</span><br><span class="line"> <span class="attribute">height</span> <span class="number">130px</span></span><br><span class="line"> <span class="attribute">position</span> relative</span><br><span class="line"> <span class="attribute">display</span> block</span><br><span class="line"> <span class="attribute">margin</span> <span class="number">15px</span> <span class="number">7px</span></span><br><span class="line"> <span class="attribute">float</span> left</span><br><span class="line"> <span class="attribute">overflow</span> hidden</span><br><span class="line"> <span class="attribute">border-radius</span> <span class="number">10px</span></span><br><span class="line"> <span class="attribute">transition</span> all .<span class="number">3s</span> ease <span class="number">0s</span>, transform .<span class="number">6s</span> <span class="built_in">cubic-bezier</span>(.<span class="number">6</span>, .<span class="number">2</span>, .<span class="number">1</span>, <span class="number">1</span>) <span class="number">0s</span></span><br><span class="line"> <span class="attribute">box-shadow</span> <span class="number">0</span> <span class="number">14px</span> <span class="number">38px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, .<span class="number">08</span>), <span class="number">0</span> <span class="number">3px</span> <span class="number">8px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, .<span class="number">06</span>)</span><br><span class="line"> <span class="selector-pseudo">&:hover</span></span><br><span class="line"> <span class="selector-class">.info</span></span><br><span class="line"> <span class="attribute">transform</span> <span class="built_in">translateY</span>(-<span class="number">100%</span>)</span><br><span class="line"> <span class="selector-class">.wrapper</span></span><br><span class="line"> <span class="selector-tag">img</span></span><br><span class="line"> <span class="attribute">transform</span> <span class="built_in">scale</span>(<span class="number">1.2</span>)</span><br><span class="line"> <span class="selector-pseudo">&::before</span></span><br><span class="line"> <span class="attribute">position</span>: fixed</span><br><span class="line"> <span class="attribute">width</span>:inherit</span><br><span class="line"> <span class="attribute">margin</span>:auto</span><br><span class="line"> <span class="attribute">left</span>:<span class="number">0</span></span><br><span class="line"> <span class="attribute">right</span>:<span class="number">0</span></span><br><span class="line"> <span class="attribute">top</span>:<span class="number">10%</span></span><br><span class="line"> <span class="attribute">border-radius</span>: <span class="number">10px</span></span><br><span class="line"> <span class="attribute">text-align</span>: center</span><br><span class="line"> <span class="attribute">z-index</span>: <span class="number">100</span></span><br><span class="line"> <span class="attribute">content</span>: <span class="built_in">attr</span>(data-title)</span><br><span class="line"> <span class="attribute">font-size</span>: <span class="number">20px</span></span><br><span class="line"> <span class="attribute">color</span>: <span class="number">#fff</span></span><br><span class="line"> <span class="attribute">padding</span>: <span class="number">10px</span></span><br><span class="line"> <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(<span class="variable">$theme</span>-color,<span class="number">0.8</span>)</span><br><span class="line"></span><br><span class="line"> <span class="selector-class">.cover</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">100%</span></span><br><span class="line"> <span class="attribute">transition</span> transform .<span class="number">5s</span> ease-out</span><br><span class="line"> <span class="selector-class">.wrapper</span></span><br><span class="line"> <span class="attribute">position</span> relative</span><br><span class="line"> <span class="selector-class">.fadeIn</span></span><br><span class="line"> <span class="attribute">animation</span> coverIn .<span class="number">8s</span> ease-out forwards</span><br><span class="line"> <span class="selector-tag">img</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">130px</span></span><br><span class="line"> <span class="attribute">pointer-events</span> none</span><br><span class="line"> <span class="selector-class">.info</span></span><br><span class="line"> <span class="attribute">display</span> flex</span><br><span class="line"> <span class="attribute">flex-direction</span> column</span><br><span class="line"> <span class="attribute">justify-content</span> center</span><br><span class="line"> <span class="attribute">align-items</span> center</span><br><span class="line"> <span class="attribute">width</span> <span class="number">100%</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">100%</span></span><br><span class="line"> <span class="attribute">overflow</span> hidden</span><br><span class="line"> <span class="attribute">border-radius</span> <span class="number">3px</span></span><br><span class="line"> <span class="attribute">background-color</span> <span class="built_in">hsla</span>(<span class="number">0</span>, <span class="number">0%</span>, <span class="number">100%</span>, .<span class="number">7</span>)</span><br><span class="line"> <span class="attribute">transition</span> transform .<span class="number">5s</span> <span class="built_in">cubic-bezier</span>(.<span class="number">6</span>, .<span class="number">2</span>, .<span class="number">1</span>, <span class="number">1</span>) <span class="number">0s</span></span><br><span class="line"> <span class="selector-tag">img</span></span><br><span class="line"> <span class="attribute">position</span> relative</span><br><span class="line"> <span class="attribute">top</span> <span class="number">22px</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">66px</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">66px</span></span><br><span class="line"> <span class="attribute">border-radius</span> <span class="number">50%</span></span><br><span class="line"> <span class="attribute">box-shadow</span> <span class="number">0</span> <span class="number">0</span> <span class="number">10px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, .<span class="number">3</span>)</span><br><span class="line"> <span class="attribute">z-index</span> <span class="number">1</span></span><br><span class="line"> <span class="attribute">text-align</span> center</span><br><span class="line"> <span class="attribute">pointer-events</span> none</span><br><span class="line"> <span class="selector-tag">span</span></span><br><span class="line"> <span class="attribute">padding</span> <span class="number">20px</span> <span class="number">10%</span> <span class="number">60px</span> <span class="number">10%</span></span><br><span class="line"> <span class="attribute">font-size</span> <span class="number">16px</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">100%</span></span><br><span class="line"> <span class="attribute">text-align</span> center</span><br><span class="line"> <span class="attribute">box-shadow</span> <span class="number">0</span> <span class="number">0</span> <span class="number">10px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, .<span class="number">3</span>)</span><br><span class="line"> <span class="attribute">background-color</span> <span class="built_in">hsla</span>(<span class="number">0</span>, <span class="number">0%</span>, <span class="number">100%</span>, .<span class="number">7</span>)</span><br><span class="line"> <span class="attribute">color</span> <span class="built_in">var</span>(--font-color)</span><br><span class="line"> <span class="attribute">white-space</span> nowrap</span><br><span class="line"> <span class="attribute">overflow</span> hidden</span><br><span class="line"> <span class="attribute">text-overflow</span> ellipsis</span><br><span class="line">.flink-list><span class="selector-tag">a</span> <span class="selector-class">.info</span>,</span><br><span class="line">.flink-list><span class="selector-tag">a</span> <span class="selector-class">.wrapper</span> <span class="selector-class">.cover</span></span><br><span class="line"> <span class="attribute">position</span> absolute</span><br><span class="line"> <span class="attribute">top</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">left</span> <span class="number">0</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width</span>:<span class="number">1024px</span>)</span><br><span class="line"> .flink-list</span><br><span class="line"> & > a</span><br><span class="line"> <span class="attribute">width</span> calc(<span class="number">33.33333%</span> - <span class="number">15px</span>)</span><br><span class="line"></span><br><span class="line">@media screen <span class="keyword">and</span> (<span class="attribute">max-width</span>:<span class="number">600px</span>)</span><br><span class="line"> .flink-list</span><br><span class="line"> & > a</span><br><span class="line"> <span class="attribute">width</span> calc(<span class="number">50%</span> - <span class="number">15px</span>)</span><br><span class="line"></span><br><span class="line">[data-theme=dark]</span><br><span class="line"> .flink-list a .info,</span><br><span class="line"> .flink-list a .info span</span><br><span class="line"> background-color rgba(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, .<span class="number">6</span>)</span><br><span class="line"> .flink-list</span><br><span class="line"> & > a</span><br><span class="line"> &:<span class="attribute">hover</span></span><br><span class="line"> &:before</span><br><span class="line"> background-color: rgba(#<span class="number">121212</span>,<span class="number">0.8</span>);</span><br><span class="line"><span class="selector-class">.justified-gallery</span> > <span class="selector-tag">div</span> > <span class="selector-tag">img</span>,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> > <span class="selector-tag">figure</span> > <span class="selector-tag">img</span>,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> > <span class="selector-tag">a</span> > <span class="selector-tag">a</span> > <span class="selector-tag">img</span>,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> > <span class="selector-tag">div</span> > <span class="selector-tag">a</span> > <span class="selector-tag">img</span>,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> > <span class="selector-tag">figure</span> > <span class="selector-tag">a</span> > <span class="selector-tag">img</span>,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> > <span class="selector-tag">a</span> > svg,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> > <span class="selector-tag">div</span> > svg,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> > <span class="selector-tag">figure</span> > svg,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> > <span class="selector-tag">a</span> > <span class="selector-tag">a</span> > svg,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> > <span class="selector-tag">div</span> > <span class="selector-tag">a</span> > svg,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> > <span class="selector-tag">figure</span> > <span class="selector-tag">a</span> > svg</span><br><span class="line"> <span class="attribute">position</span> static<span class="meta">!important</span></span><br></pre></td></tr></table></figure><hr><h2 id="时间轴生肖图标"><a href="#时间轴生肖图标" class="headerlink" title="时间轴生肖图标"></a>时间轴生肖图标</h2><p>See:<a href="https://akilar.top/posts/22257072/">https://akilar.top/posts/22257072/</a></p><p>新建 <code>[Blogroot]\themes\butterfly\scripts\year.js</code></p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">hexo.<span class="property">extend</span>.<span class="property">helper</span>.<span class="title function_">register</span>(<span class="string">'getAnimalIcon'</span>, <span class="keyword">function</span> (<span class="params">year</span>) {</span><br><span class="line"> <span class="keyword">var</span> index = <span class="built_in">parseInt</span>(year) % <span class="number">12</span>;</span><br><span class="line"> <span class="keyword">var</span> icon = {</span><br><span class="line"> <span class="number">0</span>: <span class="string">'icon-monkey'</span>,</span><br><span class="line"> <span class="number">1</span>: <span class="string">'icon-rooster'</span>,</span><br><span class="line"> <span class="number">2</span>: <span class="string">'icon-dog'</span>,</span><br><span class="line"> <span class="number">3</span>: <span class="string">'icon-boar'</span>,</span><br><span class="line"> <span class="number">4</span>: <span class="string">'icon-rat'</span>,</span><br><span class="line"> <span class="number">5</span>: <span class="string">'icon-ox'</span>,</span><br><span class="line"> <span class="number">6</span>: <span class="string">'icon-tiger'</span>,</span><br><span class="line"> <span class="number">7</span>: <span class="string">'icon-rabbit'</span>,</span><br><span class="line"> <span class="number">8</span>: <span class="string">'icon-dragon'</span>,</span><br><span class="line"> <span class="number">9</span>: <span class="string">'icon-snake'</span>,</span><br><span class="line"> <span class="number">10</span>: <span class="string">'icon-horse'</span>,</span><br><span class="line"> <span class="number">11</span>: <span class="string">'icon-goat'</span>,</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> icon[index]</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p><code>[Blogroot]\themes\butterfly\layout\includes\mixins\article-sort.pug</code> 全部</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">mixin articleSort(posts)</span><br><span class="line"> .article-sort</span><br><span class="line"> - var year</span><br><span class="line"> - posts.each(function (article) {</span><br><span class="line"> - let tempYear = date(article.date, 'YYYY')</span><br><span class="line"> - let no_cover = article.cover === false || !theme.cover.archives_enable ? 'no-article-cover' : ''</span><br><span class="line"> - let title = article.title || _p('no_title')</span><br><span class="line"> - let iconAnimal = '#'+ getAnimalIcon(tempYear)</span><br><span class="line"> if tempYear !== year</span><br><span class="line"> - year = tempYear</span><br><span class="line"> .article-sort-item.year</span><br><span class="line"> span= year</span><br><span class="line"> svg.icon(aria-hidden='true' style='width: 1em!important; height: 1em!important;')</span><br><span class="line"> use(xlink:href=iconAnimal)</span><br><span class="line"> .article-sort-item(class=no_cover)</span><br><span class="line"> if article.cover && theme.cover.archives_enable</span><br><span class="line"> a.article-sort-item-img(href=url_for(article.path) title=title)</span><br><span class="line"> img(src=url_for(article.cover) alt=title onerror=`this.onerror=null;this.src='${url_for(theme.error_img.post_page)}'`)</span><br><span class="line"> .article-sort-item-info</span><br><span class="line"> .article-sort-item-time</span><br><span class="line"> i.far.fa-calendar-alt</span><br><span class="line"> time.post-meta-date-created(datetime=date_xml(article.date) title=_p('post.created') + ' ' + full_date(article.date))= date(article.date, config.date_format)</span><br><span class="line"> a.article-sort-item-title(href=url_for(article.path) title=title)= title</span><br><span class="line"> - })</span><br></pre></td></tr></table></figure><hr><h2 id="节日挂件"><a href="#节日挂件" class="headerlink" title="节日挂件"></a>节日挂件</h2><p>See:<a href="https://akilar.top/posts/23fdf850/">https://akilar.top/posts/23fdf850/</a></p><p>新建 <code>[Blogroot]\themes\butterfly\scripts\festival.js</code></p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">hexo.<span class="property">extend</span>.<span class="property">helper</span>.<span class="title function_">register</span>(<span class="string">'getFestivalIcon'</span>, <span class="keyword">function</span> (<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">var</span> icon = [</span><br><span class="line"> <span class="string">'#icon-qiandai'</span>,</span><br><span class="line"> <span class="string">'#icon-denglong'</span>,</span><br><span class="line"> <span class="string">'#icon-juanzhou'</span>,</span><br><span class="line"> <span class="string">'#icon-hongbao'</span>,</span><br><span class="line"> <span class="string">'#icon-duilian'</span>,</span><br><span class="line"> <span class="string">'#icon-bianpao'</span>,</span><br><span class="line"> <span class="string">'#icon-shanzi'</span>,</span><br><span class="line"> <span class="string">'#icon-tangguo'</span>,</span><br><span class="line"> <span class="string">'#icon-yuanbao'</span>,</span><br><span class="line"> <span class="string">'#icon-qianchuan'</span>,</span><br><span class="line"> <span class="string">'#icon-denglong2'</span></span><br><span class="line"> ]</span><br><span class="line"> <span class="keyword">var</span> index = <span class="title class_">Math</span>.<span class="title function_">floor</span>(<span class="title class_">Math</span>.<span class="title function_">random</span>()*icon.<span class="property">length</span>);</span><br><span class="line"> <span class="keyword">return</span> icon[index]</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p><code>[Blogroot]\themes\butterfly\layout\includes\mixins\post-ui.pug</code> 14~19 行</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">if post_cover && theme.cover.index_enable</span><br><span class="line"> .post_cover(class=leftOrRight)</span><br><span class="line"> a(href=url_for(link) title=title)</span><br><span class="line"> svg.icon.festival-decoration(aria-hidden="true")</span><br><span class="line"> use(xlink:href=getFestivalIcon())</span><br><span class="line"> img.post_bg(src=url_for(post_cover) onerror=`this.onerror=null;this.src='`+ url_for(theme.error_img.post_page) + `'` alt=title)</span><br></pre></td></tr></table></figure><hr><h2 id="Swiper-Bar"><a href="#Swiper-Bar" class="headerlink" title="Swiper Bar"></a>Swiper Bar</h2><p>See:<a href="https://akilar.top/posts/8e1264d1/">https://akilar.top/posts/8e1264d1/</a></p><p>新建 <code>[Blogroot]\themes\butterfly\layout\includes\sliderbar.pug</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">.blog-slider.swiper-container-fade.swiper-container-horizontal#swiper_container</span><br><span class="line"> .blog-slider__wrp.swiper-wrapper(style='transition-duration: 0ms;')</span><br><span class="line"> if site.data.slider</span><br><span class="line"> each i in site.data.slider</span><br><span class="line"> .blog-slider__item.swiper-slide(style='width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;')</span><br><span class="line"> a.blog-slider__img(href=url_for(i.link) alt='')|</span><br><span class="line"> img(width='48' height='48' src=url_for(i.cover) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.post_page) + `'`, alt='')</span><br><span class="line"> .blog-slider__content</span><br><span class="line"> span.blog-slider__code= i.timeline</span><br><span class="line"> a.blog-slider__title(href=url_for(i.link) alt='')= i.title</span><br><span class="line"> .blog-slider__text= i.description</span><br><span class="line"> a.blog-slider__button(href=url_for(i.link) alt='')= i.button </span><br><span class="line"> .blog-slider__pagination.swiper-pagination-clickable.swiper-pagination-bullets</span><br><span class="line">script(defer src=url_for(theme.CDN.swiper_js))</span><br><span class="line">script(defer data-pjax src=url_for(theme.CDN.swiper_init))</span><br></pre></td></tr></table></figure><p><code>[Blogroot]\themes\butterfly\layout\index.pug</code></p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"> extends includes/layout.pug</span><br><span class="line"></span><br><span class="line"> block content</span><br><span class="line"> include ./includes/mixins/post-ui.pug</span><br><span class="line"> #recent-posts.recent-posts</span><br><span class="line"><span class="addition">+ .recent-post-item(style='height:auto;width:100%;')</span></span><br><span class="line"><span class="addition">+ !=partial('includes/sliderbar', {}, {cache:true})</span></span><br><span class="line"> +postUI</span><br><span class="line"> include includes/pagination.pug</span><br></pre></td></tr></table></figure><p>新建 <code>[Blogroot]\themes\butterfly\source\css\_layout\swiperstyle.styl</code></p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br></pre></td><td class="code"><pre><span class="line">*</span><br><span class="line"> <span class="attribute">box-sizing</span> border-box</span><br><span class="line">div<span class="selector-id">#swiper_container</span></span><br><span class="line"> <span class="attribute">background</span> <span class="built_in">rgba</span>(<span class="number">255</span>, <span class="number">255</span>, <span class="number">255</span>, <span class="number">0</span>);</span><br><span class="line"><span class="selector-class">.blog-slider</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">100%</span></span><br><span class="line"> <span class="attribute">position</span> relative</span><br><span class="line"> <span class="attribute">border-radius</span> <span class="number">12px</span> <span class="number">8px</span> <span class="number">8px</span> <span class="number">12px</span></span><br><span class="line"> <span class="attribute">margin</span> auto</span><br><span class="line"> <span class="attribute">background</span> <span class="built_in">var</span>(--global-bg)</span><br><span class="line"> <span class="attribute">padding</span>: <span class="number">10px</span></span><br><span class="line"> <span class="attribute">transition</span> all .<span class="number">3s</span></span><br><span class="line"></span><br><span class="line"><span class="selector-class">.blog-slider__item</span></span><br><span class="line"> <span class="attribute">display</span> flex</span><br><span class="line"> <span class="attribute">align-items</span> center</span><br><span class="line"> &<span class="selector-class">.swiper-slide-active</span></span><br><span class="line"> <span class="selector-class">.blog-slider__img</span></span><br><span class="line"> <span class="selector-tag">img</span></span><br><span class="line"> <span class="attribute">opacity</span> <span class="number">1</span></span><br><span class="line"> <span class="attribute">transition-delay</span> .<span class="number">3s</span></span><br><span class="line"> <span class="selector-class">.blog-slider__content</span></span><br><span class="line"> & > *</span><br><span class="line"> <span class="attribute">opacity</span> <span class="number">1</span></span><br><span class="line"> <span class="attribute">transform</span> none</span><br><span class="line"> & > *<span class="selector-pseudo">:nth-child</span>(<span class="number">1</span>)</span><br><span class="line"> <span class="attribute">transition-delay</span> <span class="number">0.3s</span></span><br><span class="line"> & > *<span class="selector-pseudo">:nth-child</span>(<span class="number">2</span>)</span><br><span class="line"> <span class="attribute">transition-delay</span> <span class="number">0.4s</span></span><br><span class="line"> & > *<span class="selector-pseudo">:nth-child</span>(<span class="number">3</span>)</span><br><span class="line"> <span class="attribute">transition-delay</span> <span class="number">0.5s</span></span><br><span class="line"> & > *<span class="selector-pseudo">:nth-child</span>(<span class="number">4</span>)</span><br><span class="line"> <span class="attribute">transition-delay</span> <span class="number">0.6s</span></span><br><span class="line"> & > *<span class="selector-pseudo">:nth-child</span>(<span class="number">5</span>)</span><br><span class="line"> <span class="attribute">transition-delay</span> <span class="number">0.7s</span></span><br><span class="line"> & > *<span class="selector-pseudo">:nth-child</span>(<span class="number">6</span>)</span><br><span class="line"> <span class="attribute">transition-delay</span> <span class="number">0.8s</span></span><br><span class="line"> & > *<span class="selector-pseudo">:nth-child</span>(<span class="number">7</span>)</span><br><span class="line"> <span class="attribute">transition-delay</span> <span class="number">0.9s</span></span><br><span class="line"> & > *<span class="selector-pseudo">:nth-child</span>(<span class="number">8</span>)</span><br><span class="line"> <span class="attribute">transition-delay</span> <span class="number">1s</span></span><br><span class="line"> & > *<span class="selector-pseudo">:nth-child</span>(<span class="number">9</span>)</span><br><span class="line"> <span class="attribute">transition-delay</span> <span class="number">1.1s</span></span><br><span class="line"> & > *<span class="selector-pseudo">:nth-child</span>(<span class="number">10</span>)</span><br><span class="line"> <span class="attribute">transition-delay</span> <span class="number">1.2s</span></span><br><span class="line"> & > *<span class="selector-pseudo">:nth-child</span>(<span class="number">11</span>)</span><br><span class="line"> <span class="attribute">transition-delay</span> <span class="number">1.3s</span></span><br><span class="line"> & > *<span class="selector-pseudo">:nth-child</span>(<span class="number">12</span>)</span><br><span class="line"> <span class="attribute">transition-delay</span> <span class="number">1.4s</span></span><br><span class="line"> & > *<span class="selector-pseudo">:nth-child</span>(<span class="number">13</span>)</span><br><span class="line"> <span class="attribute">transition-delay</span> <span class="number">1.5s</span></span><br><span class="line"> & > *<span class="selector-pseudo">:nth-child</span>(<span class="number">14</span>)</span><br><span class="line"> <span class="attribute">transition-delay</span> <span class="number">1.6s</span></span><br><span class="line"> & > *<span class="selector-pseudo">:nth-child</span>(<span class="number">15</span>)</span><br><span class="line"> <span class="attribute">transition-delay</span> <span class="number">1.7s</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="selector-class">.blog-slider__img</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">200px</span></span><br><span class="line"> <span class="attribute">flex-shrink</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">200px</span></span><br><span class="line"> <span class="attribute">padding</span> <span class="number">10px</span></span><br><span class="line"> <span class="attribute">border-radius</span> <span class="number">5px</span></span><br><span class="line"> <span class="attribute">transform</span> <span class="built_in">translateX</span>(<span class="number">0px</span>)</span><br><span class="line"> <span class="attribute">overflow</span> hidden</span><br><span class="line"> <span class="selector-pseudo">&:after</span></span><br><span class="line"> <span class="attribute">content</span> <span class="string">''</span></span><br><span class="line"> <span class="attribute">position</span> absolute</span><br><span class="line"> <span class="attribute">top</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">left</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">100%</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">100%</span></span><br><span class="line"> <span class="attribute">border-radius</span> <span class="number">5px</span></span><br><span class="line"> <span class="attribute">opacity</span> <span class="number">0.8</span></span><br><span class="line"> <span class="selector-tag">img</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">100%</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">100%</span></span><br><span class="line"> <span class="attribute">object-fit</span> cover</span><br><span class="line"> <span class="attribute">display</span> block</span><br><span class="line"> <span class="attribute">opacity</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">border-radius</span> <span class="number">5px</span></span><br><span class="line"> <span class="attribute">transition</span> all .<span class="number">3s</span></span><br><span class="line"></span><br><span class="line"><span class="selector-class">.blog-slider__content</span></span><br><span class="line"> <span class="attribute">padding-right</span> <span class="number">50px</span></span><br><span class="line"> <span class="attribute">padding-left</span> <span class="number">50px</span></span><br><span class="line"> & > *</span><br><span class="line"> <span class="attribute">opacity</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">transform</span> <span class="built_in">translateY</span>(<span class="number">25px</span>)</span><br><span class="line"> <span class="attribute">transition</span> all .<span class="number">4s</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="selector-class">.blog-slider__code</span></span><br><span class="line"> <span class="attribute">color</span> <span class="built_in">var</span>(--font-color)</span><br><span class="line"> <span class="attribute">margin-bottom</span> <span class="number">0px</span></span><br><span class="line"> <span class="attribute">display</span> block</span><br><span class="line"> <span class="attribute">font-weight</span> <span class="number">500</span></span><br><span class="line"></span><br><span class="line"><span class="selector-class">.blog-slider__title</span></span><br><span class="line"> <span class="attribute">font-size</span> <span class="number">18px</span></span><br><span class="line"> <span class="attribute">font-weight</span> <span class="number">700</span></span><br><span class="line"> <span class="attribute">color</span> <span class="built_in">var</span>(--font-color)</span><br><span class="line"> <span class="attribute">margin-bottom</span> <span class="number">15px</span></span><br><span class="line"> -webkit-line-clamp <span class="number">1</span></span><br><span class="line"> <span class="attribute">display</span> -webkit-box</span><br><span class="line"> <span class="attribute">overflow</span> hidden</span><br><span class="line"> -webkit-box-orient vertical</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.blog-slider__text</span></span><br><span class="line"> <span class="attribute">color</span> <span class="built_in">var</span>(--font-color)</span><br><span class="line"> -webkit-line-clamp <span class="number">1</span></span><br><span class="line"> <span class="attribute">display</span> -webkit-box</span><br><span class="line"> <span class="attribute">overflow</span> hidden</span><br><span class="line"> -webkit-box-orient vertical</span><br><span class="line"> <span class="attribute">margin-bottom</span> <span class="number">15px</span></span><br><span class="line"> <span class="attribute">line-height</span> <span class="number">1.5em</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">100%</span></span><br><span class="line"> <span class="attribute">display</span> block</span><br><span class="line"> <span class="attribute">word-break</span> break-all</span><br><span class="line"> <span class="attribute">word-wrap</span> break-word</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.blog-slider__button</span></span><br><span class="line"> <span class="attribute">display</span> inline-flex</span><br><span class="line"> <span class="attribute">background-color</span> <span class="built_in">var</span>(--btn-bg)</span><br><span class="line"> <span class="attribute">padding</span> <span class="number">4px</span> <span class="number">14px</span></span><br><span class="line"> <span class="attribute">border-radius</span> <span class="number">8px</span></span><br><span class="line"> <span class="attribute">color</span> <span class="built_in">var</span>(--btn-color)</span><br><span class="line"> <span class="attribute">text-decoration</span> none</span><br><span class="line"> <span class="attribute">font-weight</span> <span class="number">500</span></span><br><span class="line"> <span class="attribute">justify-content</span> center</span><br><span class="line"> <span class="attribute">text-align</span> center</span><br><span class="line"> <span class="attribute">letter-spacing</span> <span class="number">1px</span></span><br><span class="line"> <span class="attribute">display</span> none</span><br><span class="line"> <span class="selector-pseudo">&:hover</span></span><br><span class="line"> <span class="attribute">background-color</span> <span class="built_in">var</span>(--btn-hover-color)</span><br><span class="line"> <span class="attribute">color</span> <span class="built_in">var</span>(--btn-color)</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.blog-slider</span> <span class="selector-class">.swiper-container-horizontal</span> > <span class="selector-class">.swiper-pagination-bullets</span>, <span class="selector-class">.blog-slider</span> <span class="selector-class">.swiper-pagination-custom</span>, <span class="selector-class">.blog-slider</span> <span class="selector-class">.swiper-pagination-fraction</span></span><br><span class="line"> <span class="attribute">bottom</span> <span class="number">10px</span></span><br><span class="line"> <span class="attribute">left</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">100%</span></span><br><span class="line"></span><br><span class="line"><span class="selector-class">.blog-slider__pagination</span></span><br><span class="line"> <span class="attribute">position</span> absolute</span><br><span class="line"> <span class="attribute">z-index</span> <span class="number">21</span></span><br><span class="line"> <span class="attribute">right</span> <span class="number">20px</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">11px</span> <span class="meta">!important</span></span><br><span class="line"> <span class="attribute">text-align</span> center</span><br><span class="line"> <span class="attribute">left</span> auto <span class="meta">!important</span></span><br><span class="line"> <span class="attribute">top</span> <span class="number">50%</span></span><br><span class="line"> <span class="attribute">bottom</span> auto <span class="meta">!important</span></span><br><span class="line"> <span class="attribute">transform</span> <span class="built_in">translateY</span>(-<span class="number">50%</span>)</span><br><span class="line"> &<span class="selector-class">.swiper-pagination-bullets</span></span><br><span class="line"> <span class="selector-class">.swiper-pagination-bullet</span></span><br><span class="line"> <span class="attribute">margin</span> <span class="number">8px</span> <span class="number">0</span></span><br><span class="line"> <span class="selector-class">.swiper-pagination-bullet</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">11px</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">11px</span></span><br><span class="line"> <span class="attribute">display</span> block</span><br><span class="line"> <span class="attribute">border-radius</span> <span class="number">10px</span></span><br><span class="line"> <span class="attribute">background</span> <span class="number">#858585</span></span><br><span class="line"> <span class="attribute">opacity</span> <span class="number">0.2</span></span><br><span class="line"> <span class="attribute">transition</span> all .<span class="number">3s</span></span><br><span class="line"> <span class="selector-class">.swiper-pagination-bullet-active</span></span><br><span class="line"> <span class="attribute">opacity</span> <span class="number">1</span></span><br><span class="line"> <span class="attribute">background</span> <span class="built_in">var</span>(--btn-bg)</span><br><span class="line"> <span class="attribute">height</span> <span class="number">30px</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">600px</span>)</span><br><span class="line"> .blog-slider__pagination</span><br><span class="line"> transform translateX(-<span class="number">50%</span>)</span><br><span class="line"> left <span class="number">50%</span> !important</span><br><span class="line"> top <span class="number">320px</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">100%</span> !important</span><br><span class="line"> display flex</span><br><span class="line"> justify-content center</span><br><span class="line"> align-items center</span><br><span class="line"></span><br><span class="line"> .blog-slider__pagination</span><br><span class="line"> &.swiper-pagination-bullets</span><br><span class="line"> .swiper-pagination-bullet</span><br><span class="line"> margin <span class="number">0</span> <span class="number">5px</span></span><br><span class="line"></span><br><span class="line"> .blog-slider__pagination</span><br><span class="line"> .swiper-pagination-bullet-active</span><br><span class="line"> <span class="attribute">height</span> <span class="number">11px</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">30px</span></span><br><span class="line"></span><br><span class="line"> .blog-slider__button</span><br><span class="line"> display inline-flex</span><br><span class="line"> <span class="attribute">width</span> <span class="number">100%</span></span><br><span class="line"> .blog-slider__text</span><br><span class="line"> margin-bottom <span class="number">40px</span></span><br><span class="line"></span><br><span class="line"> .blog-slider</span><br><span class="line"> <span class="attribute">min-height</span> <span class="number">350px</span></span><br><span class="line"> <span class="attribute">height</span> auto</span><br><span class="line"> margin-top <span class="number">110px</span></span><br><span class="line"> margin-bottom <span class="number">10px</span></span><br><span class="line"></span><br><span class="line"> .blog-slider__content</span><br><span class="line"> margin-top -<span class="number">80px</span></span><br><span class="line"> text-align center</span><br><span class="line"> padding <span class="number">0</span> <span class="number">30px</span></span><br><span class="line"></span><br><span class="line"> .blog-slider__item</span><br><span class="line"> flex-direction column</span><br><span class="line"></span><br><span class="line"> .blog-slider__img</span><br><span class="line"> transform translateY(-<span class="number">50%</span>)</span><br><span class="line"> <span class="attribute">width</span> <span class="number">90%</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> .blog-slider__content</span><br><span class="line"> padding-left <span class="number">10px</span></span><br><span class="line"> padding-right <span class="number">10px</span></span><br><span class="line"></span><br><span class="line"> .blog-slider__pagination.swiper-pagination-clickable.swiper-pagination-bullets</span><br><span class="line"> top <span class="number">110px</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">@media screen <span class="keyword">and</span> (<span class="attribute">min-width</span>: <span class="number">600px</span>)</span><br><span class="line"> .blog-slider</span><br><span class="line"> <span class="attribute">height</span> <span class="number">200px</span></span><br><span class="line"></span><br><span class="line"> .blog-slider__img</span><br><span class="line"> <span class="attribute">height</span> <span class="number">200px</span></span><br></pre></td></tr></table></figure><p><code>[Blogroot]\themes\butterfly\source\css\index.styl</code> 第 1 行</p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="addition">+ @import url(hexo-config('CDN.swiper_css'))</span></span><br></pre></td></tr></table></figure><hr><h2 id="配置手机-PC-页面白天黑夜共四个背景图"><a href="#配置手机-PC-页面白天黑夜共四个背景图" class="headerlink" title="配置手机 PC 页面白天黑夜共四个背景图"></a>配置手机 PC 页面白天黑夜共四个背景图</h2><p>See:<a href="https://akilar.top/posts/23fdf850/">https://akilar.top/posts/23fdf850/</a></p><p><code>[Blogroot]\themes\butterfly\layout\includes\layout.pug</code> 14~15 行</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">- var DefaultBg = page.defaultbg ? page.defaultbg : theme.background.default</span><br><span class="line">- var DDMBg = theme.background.darkmode ? theme.background.darkmode : DefaultBg</span><br><span class="line">- var DarkmodeBg = page.darkmodebg ? page.darkmodebg : DDMBg</span><br><span class="line">if theme.background</span><br><span class="line"> #web_bg</span><br><span class="line"> if page.defaultbg || page.darkmodebg</span><br><span class="line"> style.</span><br><span class="line"> #web_bg{</span><br><span class="line"> background: #{DefaultBg} !important;</span><br><span class="line"> background-attachment: local!important;</span><br><span class="line"> background-position: center!important;</span><br><span class="line"> background-size: cover!important;</span><br><span class="line"> background-repeat: no-repeat!important;</span><br><span class="line"> }</span><br><span class="line"> [data-theme="dark"]</span><br><span class="line"> #web_bg{</span><br><span class="line"> background: #{DarkmodeBg} !important;</span><br><span class="line"> background-attachment: local!important;</span><br><span class="line"> background-position: center!important;</span><br><span class="line"> background-size: cover!important;</span><br><span class="line"> background-repeat: no-repeat!important;</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>新建 <code>[Blogroot]\themes\butterfly\source\css\_layout\web-bg.styl</code></p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">$web</span>-bg-night = <span class="built_in">hexo-config</span>(<span class="string">'background.darkmode'</span>) ? <span class="built_in">unquote</span>(<span class="built_in">hexo-config</span>(<span class="string">'background.darkmode'</span>)) : <span class="variable">$web</span>-bg</span><br><span class="line"><span class="variable">$mobile</span>-bg-day = <span class="built_in">hexo-config</span>(<span class="string">'background.mobileday'</span>) ? <span class="built_in">unquote</span>(<span class="built_in">hexo-config</span>(<span class="string">'background.mobileday'</span>)) : <span class="variable">$web</span>-bg</span><br><span class="line"><span class="variable">$mobile</span>-bg-night = <span class="built_in">hexo-config</span>(<span class="string">'background.mobilenight'</span>) ? <span class="built_in">unquote</span>(<span class="built_in">hexo-config</span>(<span class="string">'background.mobilenight'</span>)) : <span class="variable">$web</span>-bg-night</span><br><span class="line"><span class="selector-attr">[data-theme=<span class="string">"dark"</span>]</span></span><br><span class="line"> <span class="selector-id">#web_bg</span></span><br><span class="line"> <span class="attribute">background</span>: <span class="variable">$web</span>-bg-night</span><br><span class="line"> <span class="attribute">background-attachment</span>: local</span><br><span class="line"> <span class="attribute">background-position</span>: center</span><br><span class="line"> <span class="attribute">background-size</span>: cover</span><br><span class="line"> <span class="attribute">background-repeat</span>: no-repeat</span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">800px</span>)</span><br><span class="line"> #web_bg</span><br><span class="line"> background: $mobile-bg-day !important</span><br><span class="line"> background-attachment: local !important</span><br><span class="line"> background-position: center !important</span><br><span class="line"> background-size: cover !important</span><br><span class="line"> background-repeat: no-repeat !important</span><br><span class="line"> [data-theme="dark"]</span><br><span class="line"> #web_bg</span><br><span class="line"> background: $mobile-bg-night !important</span><br><span class="line"> background-attachment: local !important</span><br><span class="line"> background-position: center !important</span><br><span class="line"> background-size: cover !important</span><br><span class="line"> background-repeat: no-repeat !important</span><br></pre></td></tr></table></figure><p><code>[Blogroot]\themes\butterfly\source\css\var.styl</code> 34 行</p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"> $text-line-height = 2</span><br><span class="line"><span class="deletion">- $web-bg = hexo-config('background') && unquote(hexo-config('background'))</span></span><br><span class="line"><span class="addition">+ $web-bg = hexo-config('background.default') && unquote(hexo-config('background.default'))</span></span><br><span class="line"> $index_top_img_height = hexo-config('index_top_img_height') ? convert(hexo-config('index_top_img_height')) : 100vh</span><br></pre></td></tr></table></figure><p><code>[Blogroot]\themes\butterfly\layout\includes\third-party\pjax.pug</code> 6 行(新版已经被压缩成一行了)</p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"> script(src=url_for(theme.CDN.pjax))</span><br><span class="line"> script.</span><br><span class="line"> let pjaxSelectors = [</span><br><span class="line"> 'title',</span><br><span class="line"> '#config-diff',</span><br><span class="line"> '#body-wrap',</span><br><span class="line"> '#rightside-config-hide',</span><br><span class="line"> '#rightside-config-show',</span><br><span class="line"><span class="addition">+ '#web_bg',</span></span><br><span class="line"> '.js-pjax'</span><br><span class="line"> ]</span><br></pre></td></tr></table></figure><hr><h2 id="Copyright-beautify"><a href="#Copyright-beautify" class="headerlink" title="Copyright-beautify"></a>Copyright-beautify</h2><p>See:<a href="https://akilar.top/posts/8322f8e6/">https://akilar.top/posts/8322f8e6/</a></p><p><code>[Blogroot]\themes\butterfly\layout\includes\post\post-copyright.pug</code> 全部</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">if theme.post_copyright.enable && page.copyright !== false</span><br><span class="line"> - let author = page.copyright_author ? page.copyright_author : config.author</span><br><span class="line"> - let url = page.copyright_url ? page.copyright_url : page.permalink</span><br><span class="line"> - let license = page.license ? page.license : theme.post_copyright.license</span><br><span class="line"> - let license_url = page.license_url ? page.license_url : theme.post_copyright.license_url</span><br><span class="line"> .post-copyright</span><br><span class="line"> .post-copyright__title</span><br><span class="line"> span.post-copyright-info</span><br><span class="line"> h #[=page.title]</span><br><span class="line"> .post-copyright__type</span><br><span class="line"> span.post-copyright-info</span><br><span class="line"> a(href=url_for(url))= theme.post_copyright.decode ? decodeURI(url) : url</span><br><span class="line"> .post-copyright-m</span><br><span class="line"> .post-copyright-m-info</span><br><span class="line"> .post-copyright-a</span><br><span class="line"> h 作者</span><br><span class="line"> .post-copyright-cc-info</span><br><span class="line"> h=author</span><br><span class="line"> .post-copyright-c</span><br><span class="line"> h 发布于</span><br><span class="line"> .post-copyright-cc-info</span><br><span class="line"> h=date(page.date, config.date_format)</span><br><span class="line"> .post-copyright-u</span><br><span class="line"> h 更新于</span><br><span class="line"> .post-copyright-cc-info</span><br><span class="line"> h=date(page.updated, config.date_format)</span><br><span class="line"> .post-copyright-c</span><br><span class="line"> h 许可协议</span><br><span class="line"> .post-copyright-cc-info</span><br><span class="line"> a.icon(rel='noopener' target='_blank' title='Creative Commons' href='https://creativecommons.org/')</span><br><span class="line"> i.fab.fa-creative-commons</span><br><span class="line"> a(rel='noopener' target='_blank' title=license href=url_for(license_url))=license</span><br></pre></td></tr></table></figure><p><code>[Blogroot]\themes\butterfly\source\css\_layout\post.styl</code> 全部</p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="title">beautify</span><span class="params">()</span></span></span><br><span class="line"> <span class="built_in">headStyle</span>(fontsize)</span><br><span class="line"> <span class="attribute">padding-left</span>: <span class="built_in">unit</span>(fontsize + <span class="number">12</span>, <span class="string">'px'</span>)</span><br><span class="line"></span><br><span class="line"> <span class="selector-pseudo">&:before</span></span><br><span class="line"> <span class="attribute">margin-left</span>: <span class="built_in">unit</span>((<span class="built_in">-</span>(fontsize + <span class="number">6</span>)), <span class="string">'px'</span>)</span><br><span class="line"> <span class="attribute">font-size</span>: <span class="built_in">unit</span>(fontsize, <span class="string">'px'</span>)</span><br><span class="line"></span><br><span class="line"> <span class="selector-pseudo">&:hover</span></span><br><span class="line"> <span class="attribute">padding-left</span>: <span class="built_in">unit</span>(fontsize + <span class="number">18</span>, <span class="string">'px'</span>)</span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">h1</span>,</span><br><span class="line"> <span class="selector-tag">h2</span>,</span><br><span class="line"> <span class="selector-tag">h3</span>,</span><br><span class="line"> <span class="selector-tag">h4</span>,</span><br><span class="line"> <span class="selector-tag">h5</span>,</span><br><span class="line"> <span class="selector-tag">h6</span></span><br><span class="line"> <span class="attribute">transition</span>: all .<span class="number">2s</span> ease-out</span><br><span class="line"></span><br><span class="line"> <span class="selector-pseudo">&:before</span></span><br><span class="line"> <span class="attribute">position</span>: absolute</span><br><span class="line"> <span class="attribute">top</span>: <span class="built_in">calc</span>(<span class="number">50%</span> - <span class="number">7px</span>)</span><br><span class="line"> <span class="attribute">color</span>: <span class="variable">$title</span>-prefix-icon-color</span><br><span class="line"> <span class="attribute">content</span>: <span class="variable">$title</span>-prefix-icon</span><br><span class="line"> <span class="attribute">line-height</span>: <span class="number">1</span></span><br><span class="line"> <span class="attribute">transition</span>: all .<span class="number">2s</span> ease-out</span><br><span class="line"> <span class="keyword">@extend</span> <span class="selector-class">.fontawesomeIcon</span></span><br><span class="line"></span><br><span class="line"> <span class="selector-pseudo">&:hover</span></span><br><span class="line"> <span class="selector-pseudo">&:before</span></span><br><span class="line"> <span class="attribute">color</span>: <span class="variable">$light</span>-blue</span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">h1</span></span><br><span class="line"> <span class="built_in">headStyle</span>(<span class="number">20</span>)</span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">h2</span></span><br><span class="line"> <span class="built_in">headStyle</span>(<span class="number">18</span>)</span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">h3</span></span><br><span class="line"> <span class="built_in">headStyle</span>(<span class="number">16</span>)</span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">h4</span></span><br><span class="line"> <span class="built_in">headStyle</span>(<span class="number">14</span>)</span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">h5</span></span><br><span class="line"> <span class="built_in">headStyle</span>(<span class="number">12</span>)</span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">h6</span></span><br><span class="line"> <span class="built_in">headStyle</span>(<span class="number">12</span>)</span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">ol</span>,</span><br><span class="line"> <span class="selector-tag">ul</span></span><br><span class="line"> <span class="selector-tag">p</span></span><br><span class="line"> <span class="attribute">margin</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">8px</span></span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">li</span></span><br><span class="line"> <span class="selector-pseudo">&::marker</span></span><br><span class="line"> <span class="attribute">color</span>: <span class="variable">$light</span>-blue</span><br><span class="line"> <span class="attribute">font-weight</span>: <span class="number">600</span></span><br><span class="line"> <span class="attribute">font-size</span>: <span class="number">1.05em</span></span><br><span class="line"></span><br><span class="line"> <span class="selector-pseudo">&:hover</span></span><br><span class="line"> <span class="selector-pseudo">&::marker</span></span><br><span class="line"> <span class="attribute">color</span>: <span class="built_in">var</span>(--pseudo-hover)</span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">ul</span> > <span class="selector-tag">li</span></span><br><span class="line"> <span class="attribute">list-style-type</span>: circle</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#article-container</span></span><br><span class="line"> <span class="attribute">word-wrap</span>: break-word</span><br><span class="line"> <span class="attribute">overflow-wrap</span>: break-word</span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">a</span></span><br><span class="line"> <span class="attribute">color</span>: <span class="variable">$theme</span>-link-color</span><br><span class="line"></span><br><span class="line"> <span class="selector-pseudo">&:hover</span></span><br><span class="line"> <span class="attribute">text-decoration</span>: underline</span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">img</span></span><br><span class="line"> <span class="attribute">display</span>: block</span><br><span class="line"> <span class="attribute">margin</span>: <span class="number">0</span> auto <span class="number">20px</span></span><br><span class="line"> <span class="attribute">max-width</span>: <span class="number">100%</span></span><br><span class="line"> <span class="attribute">transition</span>: filter <span class="number">375ms</span> ease-in .<span class="number">2s</span></span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">p</span></span><br><span class="line"> <span class="attribute">margin</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">16px</span></span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">iframe</span></span><br><span class="line"> <span class="attribute">margin</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">20px</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> <span class="built_in">hexo-config</span>(<span class="string">'anchor'</span>)</span><br><span class="line"> <span class="selector-tag">a</span><span class="selector-class">.headerlink</span></span><br><span class="line"> <span class="selector-pseudo">&:after</span></span><br><span class="line"> <span class="keyword">@extend</span> <span class="selector-class">.fontawesomeIcon</span></span><br><span class="line"> <span class="attribute">float</span>: right</span><br><span class="line"> <span class="attribute">color</span>: <span class="built_in">var</span>(--headline-presudo)</span><br><span class="line"> <span class="attribute">content</span>: <span class="string">'\f0c1'</span></span><br><span class="line"> <span class="attribute">font-size</span>: .<span class="number">95em</span></span><br><span class="line"> <span class="attribute">opacity</span>: <span class="number">0</span></span><br><span class="line"> <span class="attribute">transition</span>: all .<span class="number">3s</span></span><br><span class="line"></span><br><span class="line"> <span class="selector-pseudo">&:hover</span></span><br><span class="line"> <span class="selector-pseudo">&:after</span></span><br><span class="line"> <span class="attribute">color</span>: <span class="built_in">var</span>(--pseudo-hover)</span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">h1</span>,</span><br><span class="line"> <span class="selector-tag">h2</span>,</span><br><span class="line"> <span class="selector-tag">h3</span>,</span><br><span class="line"> <span class="selector-tag">h4</span>,</span><br><span class="line"> <span class="selector-tag">h5</span>,</span><br><span class="line"> <span class="selector-tag">h6</span></span><br><span class="line"> <span class="selector-pseudo">&:hover</span></span><br><span class="line"> <span class="selector-tag">a</span><span class="selector-class">.headerlink</span></span><br><span class="line"> <span class="selector-pseudo">&:after</span></span><br><span class="line"> <span class="attribute">opacity</span>: <span class="number">1</span></span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">ol</span>,</span><br><span class="line"> <span class="selector-tag">ul</span></span><br><span class="line"> <span class="selector-tag">ol</span>,</span><br><span class="line"> <span class="selector-tag">ul</span></span><br><span class="line"> <span class="attribute">padding-left</span>: <span class="number">20px</span></span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">li</span></span><br><span class="line"> <span class="attribute">margin</span>: <span class="number">4px</span> <span class="number">0</span></span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">p</span></span><br><span class="line"> <span class="attribute">margin</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">8px</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> <span class="built_in">hexo-config</span>(<span class="string">'beautify.enable'</span>)</span><br><span class="line"> <span class="keyword">if</span> <span class="built_in">hexo-config</span>(<span class="string">'beautify.field'</span>) == <span class="string">'site'</span></span><br><span class="line"> <span class="built_in">beautify</span>()</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> <span class="built_in">hexo-config</span>(<span class="string">'beautify.field'</span>) == <span class="string">'post'</span></span><br><span class="line"> &<span class="selector-class">.post-content</span></span><br><span class="line"> <span class="built_in">beautify</span>()</span><br><span class="line"></span><br><span class="line"> > <span class="selector-pseudo">:last-child</span></span><br><span class="line"> <span class="attribute">margin-bottom</span>: <span class="number">0</span> <span class="meta">!important</span></span><br><span class="line"></span><br><span class="line"><span class="selector-id">#post</span></span><br><span class="line"> <span class="selector-class">.tag_share</span></span><br><span class="line"> <span class="selector-class">.post-meta</span></span><br><span class="line"> &__tag-list</span><br><span class="line"> <span class="attribute">display</span>: inline-block</span><br><span class="line"></span><br><span class="line"> &__tags</span><br><span class="line"> <span class="attribute">display</span>: inline-block</span><br><span class="line"> <span class="attribute">margin</span>: <span class="number">8px</span> <span class="number">8px</span> <span class="number">8px</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">padding</span>: <span class="number">0</span> <span class="number">12px</span></span><br><span class="line"> <span class="attribute">width</span>: fit-content</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="variable">$light</span>-blue</span><br><span class="line"> <span class="attribute">border-radius</span>: <span class="number">12px</span></span><br><span class="line"> <span class="attribute">color</span>: <span class="variable">$light</span>-blue</span><br><span class="line"> <span class="attribute">font-size</span>: .<span class="number">85em</span></span><br><span class="line"> <span class="attribute">transition</span>: all .<span class="number">2s</span> ease-in-out</span><br><span class="line"></span><br><span class="line"> <span class="selector-pseudo">&:hover</span></span><br><span class="line"> <span class="attribute">background</span>: <span class="variable">$light</span>-blue</span><br><span class="line"> <span class="attribute">color</span>: <span class="built_in">var</span>(--white)</span><br><span class="line"></span><br><span class="line"> <span class="selector-class">.post_share</span></span><br><span class="line"> <span class="attribute">display</span>: inline-block</span><br><span class="line"> <span class="attribute">float</span>: right</span><br><span class="line"> <span class="attribute">margin</span>: <span class="number">8px</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">width</span>: fit-content</span><br><span class="line"></span><br><span class="line"> <span class="selector-class">.social-share</span></span><br><span class="line"> <span class="attribute">font-size</span>: .<span class="number">85em</span></span><br><span class="line"></span><br><span class="line"> <span class="selector-class">.social-share-icon</span></span><br><span class="line"> <span class="attribute">margin</span>: <span class="number">0</span> <span class="number">4px</span></span><br><span class="line"> <span class="attribute">width</span>: w = <span class="number">1.85em</span></span><br><span class="line"> <span class="attribute">height</span>: w</span><br><span class="line"> <span class="attribute">font-size</span>: <span class="number">1.2em</span></span><br><span class="line"> <span class="attribute">line-height</span>: w</span><br><span class="line"></span><br><span class="line"> <span class="selector-class">.post-copyright</span></span><br><span class="line"> <span class="attribute">position</span>: relative</span><br><span class="line"> <span class="attribute">margin</span>: <span class="number">40px</span> <span class="number">0</span> <span class="number">10px</span></span><br><span class="line"> <span class="attribute">padding</span>: <span class="number">10px</span> <span class="number">16px</span></span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="built_in">var</span>(--light-grey)</span><br><span class="line"> <span class="attribute">transition</span>: box-shadow .<span class="number">3s</span> ease-in-out</span><br><span class="line"> <span class="attribute">overflow</span>: hidden</span><br><span class="line"> <span class="attribute">border-radius</span>: <span class="number">12px</span><span class="meta">!important</span></span><br><span class="line"> <span class="attribute">background-color</span>: <span class="built_in">rgb</span>(<span class="number">239</span> <span class="number">241</span> <span class="number">243</span>)</span><br><span class="line"></span><br><span class="line"> <span class="selector-pseudo">&:before</span></span><br><span class="line"> <span class="attribute">background</span> <span class="built_in">var</span>(--heo-post-blockquote-bg)</span><br><span class="line"> <span class="attribute">position</span> absolute</span><br><span class="line"> <span class="attribute">right</span> -<span class="number">26px</span></span><br><span class="line"> <span class="attribute">top</span> -<span class="number">120px</span></span><br><span class="line"> <span class="attribute">content</span> <span class="string">'\f25e'</span></span><br><span class="line"> <span class="attribute">font-size</span> <span class="number">200px</span></span><br><span class="line"> <span class="attribute">font-family</span> <span class="string">'Font Awesome 5 Brands'</span></span><br><span class="line"> <span class="attribute">opacity</span> .<span class="number">2</span></span><br><span class="line"></span><br><span class="line"> <span class="selector-pseudo">&:hover</span></span><br><span class="line"> <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">8px</span> <span class="number">0</span> <span class="built_in">rgba</span>(<span class="number">232</span>, <span class="number">237</span>, <span class="number">250</span>, .<span class="number">6</span>), <span class="number">0</span> <span class="number">2px</span> <span class="number">4px</span> <span class="number">0</span> <span class="built_in">rgba</span>(<span class="number">232</span>, <span class="number">237</span>, <span class="number">250</span>, .<span class="number">5</span>)</span><br><span class="line"></span><br><span class="line"> <span class="selector-class">.post-copyright</span></span><br><span class="line"> &-meta</span><br><span class="line"> <span class="attribute">color</span>: <span class="variable">$light</span>-blue</span><br><span class="line"> <span class="attribute">font-weight</span>: bold</span><br><span class="line"></span><br><span class="line"> &-info</span><br><span class="line"> <span class="attribute">padding-left</span>: <span class="number">6px</span></span><br><span class="line"></span><br><span class="line"> <span class="selector-tag">a</span></span><br><span class="line"> <span class="attribute">text-decoration</span>: none</span><br><span class="line"> <span class="attribute">word-break</span>: break-word</span><br><span class="line"></span><br><span class="line"> <span class="selector-pseudo">&:hover</span></span><br><span class="line"> <span class="attribute">text-decoration</span>: none</span><br><span class="line"></span><br><span class="line"> <span class="selector-class">.post-copyright-cc-info</span></span><br><span class="line"> <span class="attribute">color</span>: <span class="variable">$theme</span>-color;</span><br><span class="line"></span><br><span class="line"> <span class="selector-class">.post-outdate-notice</span></span><br><span class="line"> <span class="attribute">position</span>: relative</span><br><span class="line"> <span class="attribute">margin</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">20px</span></span><br><span class="line"> <span class="attribute">padding</span>: .<span class="number">5em</span> <span class="number">1.2em</span></span><br><span class="line"> <span class="attribute">border-radius</span>: <span class="number">3px</span></span><br><span class="line"> <span class="attribute">background-color</span>: <span class="variable">$noticeOutdate</span>-bg</span><br><span class="line"> <span class="attribute">color</span>: <span class="variable">$noticeOutdate</span>-color</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> <span class="built_in">hexo-config</span>(<span class="string">'noticeOutdate.style'</span>) == <span class="string">'flat'</span></span><br><span class="line"> <span class="attribute">padding</span>: .<span class="number">5em</span> <span class="number">1em</span> .<span class="number">5em</span> <span class="number">2.6em</span></span><br><span class="line"> <span class="attribute">border-left</span>: <span class="number">5px</span> solid <span class="variable">$noticeOutdate</span>-border</span><br><span class="line"></span><br><span class="line"> <span class="selector-pseudo">&:before</span></span><br><span class="line"> <span class="keyword">@extend</span> <span class="selector-class">.fontawesomeIcon</span></span><br><span class="line"> <span class="attribute">position</span>: absolute</span><br><span class="line"> <span class="attribute">top</span>: <span class="number">50%</span></span><br><span class="line"> <span class="attribute">left</span>: .<span class="number">9em</span></span><br><span class="line"> <span class="attribute">color</span>: <span class="variable">$noticeOutdate</span>-border</span><br><span class="line"> <span class="attribute">content</span>: <span class="string">'\f071'</span></span><br><span class="line"> <span class="attribute">transform</span>: <span class="built_in">translateY</span>(-<span class="number">50%</span>)</span><br><span class="line"></span><br><span class="line"> <span class="selector-class">.ads-wrap</span></span><br><span class="line"> <span class="attribute">margin</span>: <span class="number">40px</span> <span class="number">0</span></span><br><span class="line"><span class="selector-class">.post-copyright-m-info</span></span><br><span class="line"> <span class="selector-class">.post-copyright-a</span>,</span><br><span class="line"> <span class="selector-class">.post-copyright-c</span>,</span><br><span class="line"> <span class="selector-class">.post-copyright-u</span></span><br><span class="line"> <span class="attribute">display</span> inline-block</span><br><span class="line"> <span class="attribute">width</span> fit-content</span><br><span class="line"> <span class="attribute">padding</span> <span class="number">2px</span> <span class="number">5px</span></span><br><span class="line"><span class="selector-attr">[data-theme=<span class="string">"dark"</span>]</span></span><br><span class="line"> <span class="selector-id">#post</span></span><br><span class="line"> <span class="selector-class">.post-copyright</span></span><br><span class="line"> <span class="attribute">background-color</span> <span class="number">#07080a</span></span><br><span class="line"> <span class="attribute">text-shadow</span> <span class="number">#bfbeb8</span> <span class="number">0</span> <span class="number">0</span> <span class="number">2px</span></span><br><span class="line"> <span class="attribute">border</span> <span class="number">1px</span> solid <span class="built_in">rgb</span>(<span class="number">19</span> <span class="number">18</span> <span class="number">18</span> / <span class="number">35%</span>)</span><br><span class="line"> <span class="attribute">box-shadow</span> <span class="number">0</span> <span class="number">0</span> <span class="number">5px</span> <span class="built_in">rgb</span>(<span class="number">20</span>, <span class="number">120</span>, <span class="number">210</span>)</span><br><span class="line"> <span class="attribute">animation</span> flashlight <span class="number">1s</span> linear infinite alternate</span><br><span class="line"> <span class="selector-class">.post-copyright-info</span></span><br><span class="line"> <span class="attribute">color</span> <span class="number">#e0e0e4</span></span><br><span class="line"></span><br><span class="line"><span class="selector-id">#post</span></span><br><span class="line"> <span class="selector-class">.post-copyright__title</span></span><br><span class="line"> <span class="attribute">font-size</span> <span class="number">22px</span></span><br><span class="line"> <span class="selector-class">.post-copyright__notice</span></span><br><span class="line"> <span class="attribute">font-size</span> <span class="number">15px</span></span><br><span class="line"> <span class="selector-class">.post-copyright</span></span><br><span class="line"> <span class="attribute">box-shadow</span> <span class="number">2px</span> <span class="number">2px</span> <span class="number">5px</span></span><br></pre></td></tr></table></figure><hr><h2 id="Butterfly-comment-board-beautify"><a href="#Butterfly-comment-board-beautify" class="headerlink" title="Butterfly comment board beautify"></a>Butterfly comment board beautify</h2><p>See:<a href="https://akilar.top/posts/397b8b90/">https://akilar.top/posts/397b8b90/</a></p><p><code>[Blogroot]\themes\butterfly\layout\includes\rightside.pug</code></p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"> if commentsJsLoad</span><br><span class="line"><span class="deletion">- a#to_comment(href="#post-comment" title=_p("rightside.scroll_to_comment"))</span></span><br><span class="line"><span class="addition">+ button#to_comment(type="button" title=_p("rightside.scroll_to_comment") onclick="FixedCommentBtn();")</span></span><br></pre></td></tr></table></figure><hr><p>新建 <code>[Blogroot]\themes\butterfly\source\css\_layout\fixed_card_widget.styl</code></p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 垂直居中卡片样式(排除toc目录卡片)</span></span><br><span class="line"><span class="selector-class">.fixed-card-widget</span></span><br><span class="line"> <span class="selector-pseudo">&:not</span>(#card-toc)</span><br><span class="line"> <span class="attribute">visibility</span> visible<span class="meta">!important</span></span><br><span class="line"> <span class="attribute">display</span> block<span class="meta">!important</span></span><br><span class="line"> <span class="attribute">position</span> fixed<span class="meta">!important</span></span><br><span class="line"> <span class="attribute">bottom</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">left</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">top</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">right</span> <span class="number">0</span></span><br><span class="line"> <span class="attribute">margin</span> auto</span><br><span class="line"> <span class="attribute">margin-bottom</span> auto<span class="meta">!important</span></span><br><span class="line"> <span class="attribute">margin-top</span> auto<span class="meta">!important</span></span><br><span class="line"> <span class="attribute">max-width</span> <span class="number">300px</span></span><br><span class="line"> <span class="attribute">max-height</span> <span class="number">500px</span></span><br><span class="line"> <span class="attribute">width</span> auto</span><br><span class="line"> <span class="attribute">height</span> fit-content</span><br><span class="line"> <span class="attribute">z-index</span> <span class="number">999</span></span><br><span class="line"> <span class="attribute">animation</span> rotateX <span class="number">0.5s</span> ease</span><br><span class="line"> <span class="attribute">animation-fill-mode</span> forwards</span><br><span class="line"><span class="comment">// 针对说说卡片做样式兼容适配</span></span><br><span class="line"><span class="selector-class">.card-shuo</span></span><br><span class="line"> &<span class="selector-class">.fixed-card-widget</span></span><br><span class="line"> <span class="selector-id">#artitalk_main</span></span><br><span class="line"> <span class="attribute">max-height</span> <span class="number">460px</span></span><br><span class="line"> <span class="attribute">overflow</span> scroll</span><br><span class="line"> &::-webkit-scrollbar</span><br><span class="line"> <span class="attribute">display</span>: none</span><br><span class="line"> <span class="selector-id">#operare_artitalk</span></span><br><span class="line"> <span class="selector-class">.c2</span></span><br><span class="line"> <span class="attribute">z-index</span> <span class="number">1000</span></span><br><span class="line"><span class="comment">// 针对标签卡片做样式兼容适配</span></span><br><span class="line"><span class="selector-class">.card-tags</span></span><br><span class="line"> &<span class="selector-class">.fixed-card-widget</span></span><br><span class="line"> <span class="selector-class">.card-tag-cloud</span></span><br><span class="line"> <span class="attribute">max-height</span> <span class="number">460px</span></span><br><span class="line"> <span class="attribute">overflow</span> scroll</span><br><span class="line"> &::-webkit-scrollbar</span><br><span class="line"> <span class="attribute">display</span>: none</span><br><span class="line"><span class="comment">// 控制手机端可见</span></span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">768px</span>)</span><br><span class="line"> div#fixedcard-dashboard</span><br><span class="line"> display flex!important</span><br><span class="line">// 侧栏悬浮按钮样式</span><br><span class="line">div#fixedcard-dashboard</span><br><span class="line"> position fixed</span><br><span class="line"> top <span class="number">150px</span></span><br><span class="line"> <span class="attribute">width</span> fit-content</span><br><span class="line"> <span class="attribute">height</span> <span class="number">40px</span></span><br><span class="line"> opacity <span class="number">0.3</span></span><br><span class="line"> transition all <span class="number">0.5s</span></span><br><span class="line"> display none</span><br><span class="line"> background rgba(<span class="number">255</span>,<span class="number">255</span>,<span class="number">255</span>,<span class="number">0.9</span>)</span><br><span class="line"> padding <span class="number">5px</span> <span class="number">10px</span></span><br><span class="line"> border-top-right-radius <span class="number">20px</span></span><br><span class="line"> border-bottom-right-radius <span class="number">20px</span></span><br><span class="line"> z-index <span class="number">1000</span></span><br><span class="line"> &:<span class="attribute">hover</span></span><br><span class="line"> opacity <span class="number">1</span></span><br><span class="line"> button</span><br><span class="line"> &.fixedcard-activebtn</span><br><span class="line"> <span class="attribute">width</span> <span class="number">30px</span></span><br><span class="line"> opacity <span class="number">1</span></span><br><span class="line"> pointer-events all</span><br><span class="line">// 按钮样式</span><br><span class="line">button</span><br><span class="line"> &.fixedcard-activebtn</span><br><span class="line"> <span class="attribute">width</span> <span class="number">0px</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">30px</span></span><br><span class="line"> transition all .<span class="number">5s</span></span><br><span class="line"> display flex</span><br><span class="line"> opacity <span class="number">0</span></span><br><span class="line"> align-items center</span><br><span class="line"> justify-content space-around</span><br><span class="line"> pointer-events none</span><br><span class="line"> <span class="attribute">color</span> #<span class="number">757273</span></span><br><span class="line">// 悬浮按钮头像</span><br><span class="line">.fixedcard-user-avatar</span><br><span class="line"> display inline-block</span><br><span class="line"> img</span><br><span class="line"> &.fixedcard-user-avatar-img</span><br><span class="line"> <span class="attribute">width</span> <span class="number">30px</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">30px</span></span><br><span class="line"> border-radius <span class="number">50%</span></span><br><span class="line">// 悬浮按钮夜间模式适配</span><br><span class="line">[data-theme="dark"]</span><br><span class="line"> div#fixedcard-dashboard</span><br><span class="line"> background rgba(<span class="number">55</span>,<span class="number">55</span>,<span class="number">55</span>,<span class="number">0.9</span>)</span><br><span class="line"> button</span><br><span class="line"> &.fixedcard-activebtn</span><br><span class="line"> <span class="attribute">color</span> #bcbdbd</span><br><span class="line"></span><br><span class="line">// 卡片开启动画效果</span><br><span class="line">@keyframes rotateX</span><br><span class="line"> from</span><br><span class="line"> transform rotateX(<span class="number">90deg</span>)</span><br><span class="line"> to</span><br><span class="line"> transform rotateX(<span class="number">0deg</span>)</span><br><span class="line">// 退出蒙版效果</span><br><span class="line">div#quit-box</span><br><span class="line"> position fixed</span><br><span class="line"> display block</span><br><span class="line"> left <span class="number">0</span></span><br><span class="line"> top <span class="number">0</span></span><br><span class="line"> <span class="attribute">width</span> <span class="number">100vh</span></span><br><span class="line"> <span class="attribute">height</span> <span class="number">100vh</span></span><br><span class="line"> z-index <span class="number">99</span></span><br><span class="line"> background rgba(<span class="number">25</span>,<span class="number">25</span>,<span class="number">25</span>,<span class="number">0.3</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">[data-theme="dark"]</span><br><span class="line"> div#quit-box</span><br><span class="line"> background rgba(<span class="number">147</span>, <span class="number">146</span>, <span class="number">128</span>, <span class="number">0.3</span>)</span><br></pre></td></tr></table></figure><p>新建 <code>[Blogroot]\themes\butterfly\layout\includes\fixed_card_widget.pug</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">#fixedcard-dashboard</span><br><span class="line"> if is_post()</span><br><span class="line"> each poitem in theme.fixed_card_widget.post</span><br><span class="line"> button.fixedcard-activebtn(type="button" title=poitem.title onclick=`FixedCardWidget("` + poitem.type + `","` + poitem.name + `","` + poitem.index + `")`)</span><br><span class="line"> i(class=poitem.icon)</span><br><span class="line"> else</span><br><span class="line"> each paitem in theme.fixed_card_widget.page</span><br><span class="line"> button.fixedcard-activebtn(type="button" title=paitem.title onclick=`FixedCardWidget("` + paitem.type + `","` + paitem.name + `","` + paitem.index + `")`)</span><br><span class="line"> i(class=paitem.icon)</span><br><span class="line"> .fixedcard-user-avatar.fixedcard-activebtn(onclick="RemoveFixedCardWidget()")</span><br><span class="line"> img.fixedcard-user-avatar-img(src=url_for(theme.avatar.img) title=config.author)</span><br></pre></td></tr></table></figure><p><code>[Blogroot]\themes\butterfly\layout\includes\additional-js.pug</code> 末尾</p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"> if theme.busuanzi.site_uv || theme.busuanzi.site_pv || theme.busuanzi.page_pv</span><br><span class="line"> script(async data-pjax src=url_for(theme.CDN.busuanzi))</span><br><span class="line"><span class="addition">+ if !theme.aside.mobile && theme.fixed_card_widget.enable</span></span><br><span class="line"><span class="addition">+ include ./fixed_card_widget.pug</span></span><br></pre></td></tr></table></figure><p><code>[Blogroot]\themes\butterfly\layout\includes\third-party\pjax.pug</code> 6 行</p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"> script.</span><br><span class="line"> let pjaxSelectors = [</span><br><span class="line"> 'title',</span><br><span class="line"> '#config-diff',</span><br><span class="line"> '#body-wrap',</span><br><span class="line"> '#rightside-config-hide',</span><br><span class="line"> '#rightside-config-show',</span><br><span class="line"><span class="addition">+ '#fixedcard-dashboard',</span></span><br><span class="line"> '.js-pjax'</span><br><span class="line"> ]</span><br></pre></td></tr></table></figure><hr><h2 id="导航栏魔改"><a href="#导航栏魔改" class="headerlink" title="导航栏魔改"></a>导航栏魔改</h2><p><code>[Blogroot]\themes\butterfly\layout\includes\header\nav.pug</code> 全部</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">nav#nav</span><br><span class="line"> span#blog_name</span><br><span class="line"> a#site-name(href=url_for('/')) #[=config.title]</span><br><span class="line"> </span><br><span class="line"> #menus</span><br><span class="line"> !=partial('includes/header/menu_item', {}, {cache: true})</span><br><span class="line"> #nav-right</span><br><span class="line"> if (theme.algolia_search.enable || theme.local_search.enable)</span><br><span class="line"> #search-button</span><br><span class="line"> a.site-page.social-icon.search</span><br><span class="line"> i.fas.fa-search.fa-fw</span><br><span class="line"> span=' '+_p('search.title')</span><br><span class="line"> #darkmode_navswitch</span><br><span class="line"> a.nav-rightbutton.site-page.darkmode_switchbutton(onclick='switchNightMode()', title=_p('rightside.night_mode_title'))</span><br><span class="line"> i.fas.fa-adjust</span><br><span class="line"></span><br><span class="line"> #toggle-menu</span><br><span class="line"> a.site-page</span><br><span class="line"> i.fas.fa-bars.fa-fw</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">主要是记录魔改网站源代码的部分,方便升级之后重新魔改。</summary>
<category term="网站" scheme="https://blog.liynw.top/categories/%E7%BD%91%E7%AB%99/"/>
<category term="Hexo" scheme="https://blog.liynw.top/tags/Hexo/"/>
<category term="butterfly" scheme="https://blog.liynw.top/tags/butterfly/"/>
</entry>
<entry>
<title>树链剖分 / 轻重链剖分</title>
<link href="https://blog.liynw.top/posts/534cd243/"/>
<id>https://blog.liynw.top/posts/534cd243/</id>
<published>2022-05-14T20:34:14.000Z</published>
<updated>2022-05-14T20:34:14.000Z</updated>
<content type="html"><![CDATA[<h2 id="前置芝士"><a href="#前置芝士" class="headerlink" title="前置芝士"></a>前置芝士</h2><ul><li><a href="/posts/8893d943/">线段树</a>(链的查询)</li><li><a href="/posts/c2587cc4/">树形 DP</a>(树上 DFS 预处理)</li></ul><hr><h2 id="概念-amp-性质"><a href="#概念-amp-性质" class="headerlink" title="概念 & 性质"></a>概念 & 性质</h2><p>处理一棵树会比较棘手,但是如果我们有办法把这棵树处理成一条一条的链,那就好解决多了。</p><p>树链剖分,简称树剖,就是干的这事。树链剖分有两种方法:重链剖分和长链剖分。因为长链剖分不常用,所以这一篇介绍的的都是重链剖分。</p><p>在了解接下来的内容之前,先要了解几个概念。</p><ul><li>重儿子:每个子树中,子树大小(即子树包含节点数)最大的子节点</li><li>轻儿子:除重儿子外的其他子节点</li><li>重边:每个节点与其重儿子间的边</li><li>轻边:每个节点与其轻儿子间的边</li><li>重链:重边连成的链</li><li>轻链:轻边连成的链</li></ul><p>大家发现没有,这里有三组相对的概念。为了更好的理解这几个概念,让我们在 mjl 的 PPT 上白嫖一棵树过来:</p><p><img src="https://pic.imgdb.cn/item/627fa5120947543129364fc8.jpg" alt=""></p><p>因为单独一个节点也可以看作重链,所以这棵树上的重链分布如下:</p><p><img src="https://pic.imgdb.cn/item/627fa4e2094754312935aab7.jpg" alt=""></p><p>颜色标出来应该就很清晰了,每一条重链的链头都是轻儿子,后面全部都是重儿子。</p><p>因为 Hexo 对 $\LaTeX$ 的支持很不友好,所以窝直接从 luogu 的博客上截图截下来了 qwq。</p><p>除了上面说的,重链还有几个性质:</p><ol><li>每一个节点只能在一条重链上,而且必定在重链上。(原因:每个节点只有一个重儿子。)</li><li>一个点到根节点的路径上最有只有 $\log n$ 条轻边。(原因:若 $v$ 为 $u$ 子节点且 $(u,v)$ 为轻边,则子树大小 $2sum_v\le sum_u$。)</li></ol><hr><h2 id="树链剖分の基本解法"><a href="#树链剖分の基本解法" class="headerlink" title="树链剖分の基本解法"></a>树链剖分の基本解法</h2><h3 id="两个-DFS-预处理"><a href="#两个-DFS-预处理" class="headerlink" title="两个 DFS 预处理"></a>两个 DFS 预处理</h3><p>既然每一条重链的头都是轻儿子,我们可以通过标记每一个节点所在重链的链头节点的方法来存储重链。在此之前,我们要开几个数组:</p><ul><li>$ft_u$: $u$ 的父节点;根节点 $ft_1=0$</li><li>$dep_u$: $u$ 节点的深度</li><li>$sum_u$: 以 $u$ 为根节点的子树的大小</li><li>$son_u$: $u$ 的重儿子;叶子节点 $son_u=0$</li><li>$top_u$: $u$ 所在重链的链头节点</li></ul><p>第一个 DFS 需要做以下事情:</p><ol><li>初始化每一个节点的父节点 $ft$,深度 $dep$ 和子树大小 $sum$;</li><li>求出每一个非叶子节点的重儿子 $son$。</li></ol><p>代码长这样:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs1</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> fa)</span> </span>{ <span class="comment">// u 为遍历到的节点,fa 为 u 的父节点</span></span><br><span class="line"> ft[u] = fa; <span class="comment">// 初始化 ft 数组</span></span><br><span class="line"> <span class="type">int</span> len = G[u].<span class="built_in">size</span>() - <span class="number">1</span>, mx = <span class="number">0</span>; <span class="comment">// mx 存 u 的儿子中子树大小的最大值</span></span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) { <span class="comment">// 遍历 u 的子节点</span></span><br><span class="line"> <span class="type">int</span> v = G[u][i];</span><br><span class="line"> <span class="keyword">if</span>(v != fa) {</span><br><span class="line"> dep[v] = dep[u] + <span class="number">1</span>; <span class="comment">// 初始化 dep 数组,是父亲向儿子转移,记得写在 dfs 的前面</span></span><br><span class="line"> <span class="built_in">dfs1</span>(v, u);</span><br><span class="line"> sum[u] += sum[v]; <span class="comment">// 累加 u 的子树大小</span></span><br><span class="line"> <span class="keyword">if</span>(sum[v] > mx) { <span class="comment">// 判断重儿子</span></span><br><span class="line"> mx = sum[v]; <span class="comment">// 更新最大子树大小</span></span><br><span class="line"> son[u] = v; <span class="comment">// 更新 u 的重儿子</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> ++sum[u]; <span class="comment">// 别忘了把 u 自己加上</span></span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>第二个 DFS 的任务很简单:</p><ol><li>算出 $top$ 数组。</li><li>(可选)如果后面需要用 dfs 序(可能性很大)也需要求一下。</li></ol><p>代码长这样:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs2</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> fa, <span class="type">int</span> tp)</span> </span>{ <span class="comment">// u、fa 含义同上,tp 为目前重链的链头</span></span><br><span class="line"> top[u] = tp; <span class="comment">// 初始化 top 数组</span></span><br><span class="line"> dfn[++tot] = w[u]; <span class="comment">// 求 dfs 序</span></span><br><span class="line"> id[u] = tot; <span class="comment">// 存一下每一个节点在 dfs 序中出现的位置</span></span><br><span class="line"> <span class="type">int</span> len = G[u].<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span>(son[u]) <span class="comment">// 先搜重儿子</span></span><br><span class="line"> <span class="built_in">dfs2</span>(son[u], u, tp); <span class="comment">// 重链还是那一根,所以链头不变</span></span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) { <span class="comment">// 搜轻儿子</span></span><br><span class="line"> <span class="type">int</span> v = G[u][i];</span><br><span class="line"> <span class="keyword">if</span>(v != fa && v != son[u])</span><br><span class="line"> <span class="built_in">dfs2</span>(v, u, v); <span class="comment">// 换了一根重链,轻儿子做链头</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>这个代码遗留了两个问题:</p><ol><li><p>为什么 dfs 序只需要加一次节点?</p><p> A:其实加一次或者两次两种写法都是对的,加一遍会更方便,两遍对于子树的更新思考起来比较好想出来,下文讲解使用加一遍的方法,两种写法的代码都有,供参考。 </p></li><li><p>为啥要先搜重儿子?</p><p> A:为了让 dfs 序中每一条重链都连在一起,重儿子之间没有轻儿子捣乱,方便后面跳重链的时候用线段树维护。</p></li></ol><hr><h2 id="树链剖分の妙用"><a href="#树链剖分の妙用" class="headerlink" title="树链剖分の妙用"></a>树链剖分の妙用</h2><h3 id="1-求-LCA"><a href="#1-求-LCA" class="headerlink" title="1. 求 LCA"></a>1. 求 LCA</h3><p>详情请见 <a href="/posts/d17dcd42/#树链剖分">LCA 文章中的树剖解法</a>。</p><h3 id="2-在树上维护线段树"><a href="#2-在树上维护线段树" class="headerlink" title="2. 在树上维护线段树"></a>2. 在树上维护线段树</h3><p>利用树剖把树转换为线性的链的特征,结合 dfs 序,可以利用树剖在树上维护线段树,从而达到一些目的。</p><p>例题:<a href="https://www.luogu.com.cn/problem/P3384">【模板】树链剖分/轻重链剖分</a></p><p>要求维护的操作是两点之间的简单路径和子树的修改与查询,很明显可以用 dfs 序把树转换为数组再用线段树维护。</p><p>首先子树比较好操作,因为 dfs 序中子树是连在一起的,故以 $u$ 为根节点的子树在 dfs 序中的范围就是 $[id_u,id_u+sum_u-1]$,用区间修改、区间查询的线段树维护即可。</p><p>维护两节点之间的简单路径需要参考求 LCA 的方法,因为 $u,v$ 跳上去的路径就是这条简单路径。由于 $u,v$ 在跳到一条重链上之前都是一条一条跳重链,所以我们可以一边跳一边用线段树维护这些重链。最后两节点到一条重链上之后,再维护两节点之间的区间即可。我们生成 dfs 序的规则保证了这些区间都是连续的。</p><p>代码还挺难打的,我调了一个上午/kk。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @file P3384.cpp</span></span><br><span class="line"><span class="comment"> * @author Liynw</span></span><br><span class="line"><span class="comment"> * @brief 树链剖分(轻重链剖分)模板</span></span><br><span class="line"><span class="comment"> * @date 2022-05-03</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * @copyright Copyright (c) 2022</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><vector></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> int long long</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>)<span class="number">1e6</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, q, r, mod, tot, w[maxn], ft[maxn], son[maxn], sum[maxn], dep[maxn], top[maxn], id[maxn], dfn[maxn << <span class="number">1</span>];</span><br><span class="line">std::vector<<span class="type">int</span>> G[maxn];</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> Segment_Tree {</span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">_</span> {</span><br><span class="line"> <span class="type">int</span> val, target, len;</span><br><span class="line">} t[maxn << <span class="number">2</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">swap</span><span class="params">(<span class="type">int</span> &x, <span class="type">int</span> &y)</span> </span>{ x ^= y, y ^= x, x ^= y; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">build</span><span class="params">(<span class="type">int</span> p, <span class="type">int</span> l, <span class="type">int</span> r)</span> </span>{</span><br><span class="line"> t[p].len = r - l + <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span>(l == r) {</span><br><span class="line"> t[p].val = dfn[l];</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="type">int</span> lc = p << <span class="number">1</span>, rc = p << <span class="number">1</span> | <span class="number">1</span>, mid = (l + r) >> <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">build</span>(lc, l, mid);</span><br><span class="line"> <span class="built_in">build</span>(rc, mid + <span class="number">1</span>, r);</span><br><span class="line"> t[p].val = t[lc].val + t[rc].val;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">pushdown</span><span class="params">(<span class="type">int</span> p)</span> </span>{</span><br><span class="line"> <span class="type">int</span> l = p << <span class="number">1</span>, r = p << <span class="number">1</span> | <span class="number">1</span>;</span><br><span class="line"> t[l].val += t[l].len * t[p].target;</span><br><span class="line"> t[r].val += t[r].len * t[p].target;</span><br><span class="line"> t[l].target += t[p].target;</span><br><span class="line"> t[r].target += t[p].target;</span><br><span class="line"> t[p].target = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">update</span><span class="params">(<span class="type">int</span> p, <span class="type">int</span> l, <span class="type">int</span> r, <span class="type">int</span> L, <span class="type">int</span> R, <span class="type">int</span> k)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(L <= l && r <= R) {</span><br><span class="line"> t[p].val += t[p].len * k;</span><br><span class="line"> t[p].target += k;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">pushdown</span>(p);</span><br><span class="line"> <span class="type">int</span> lc = p << <span class="number">1</span>, rc = p << <span class="number">1</span> | <span class="number">1</span>, mid = (l + r) >> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span>(L <= mid)</span><br><span class="line"> <span class="built_in">update</span>(lc, l, mid, L, R, k);</span><br><span class="line"> <span class="keyword">if</span>(R > mid)</span><br><span class="line"> <span class="built_in">update</span>(rc, mid + <span class="number">1</span>, r, L, R, k);</span><br><span class="line"> t[p].val = t[lc].val + t[rc].val;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">query</span><span class="params">(<span class="type">int</span> p, <span class="type">int</span> l, <span class="type">int</span> r, <span class="type">int</span> L, <span class="type">int</span> R)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(L <= l && r <= R)</span><br><span class="line"> <span class="keyword">return</span> t[p].val;</span><br><span class="line"> <span class="built_in">pushdown</span>(p);</span><br><span class="line"> <span class="type">int</span> lc = p << <span class="number">1</span>, rc = p << <span class="number">1</span> | <span class="number">1</span>, mid = (l + r) >> <span class="number">1</span>, sum = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">if</span>(L <= mid)</span><br><span class="line"> sum += <span class="built_in">query</span>(lc, l, mid, L, R);</span><br><span class="line"> <span class="keyword">if</span>(R > mid)</span><br><span class="line"> sum += <span class="built_in">query</span>(rc, mid + <span class="number">1</span>, r, L, R);</span><br><span class="line"> <span class="keyword">return</span> sum;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> Segment_Tree;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs1</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> fa)</span> </span>{</span><br><span class="line"> ft[u] = fa;</span><br><span class="line"> <span class="type">int</span> len = G[u].<span class="built_in">size</span>() - <span class="number">1</span>, mx = <span class="number">0</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) {</span><br><span class="line"> <span class="type">int</span> v = G[u][i];</span><br><span class="line"> <span class="keyword">if</span>(v != fa) {</span><br><span class="line"> dep[v] = dep[u] + <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">dfs1</span>(v, u);</span><br><span class="line"> sum[u] += sum[v];</span><br><span class="line"> <span class="keyword">if</span>(sum[v] > mx) {</span><br><span class="line"> mx = sum[v];</span><br><span class="line"> son[u] = v;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> ++sum[u];</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs2</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> fa, <span class="type">int</span> tp)</span> </span>{</span><br><span class="line"> top[u] = tp;</span><br><span class="line"> dfn[++tot] = w[u];</span><br><span class="line"> id[u] = tot;</span><br><span class="line"> <span class="type">int</span> len = G[u].<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span>(son[u]) {</span><br><span class="line"> <span class="built_in">dfs2</span>(son[u], u, tp);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) {</span><br><span class="line"> <span class="type">int</span> v = G[u][i];</span><br><span class="line"> <span class="keyword">if</span>(v != fa && v != son[u])</span><br><span class="line"> <span class="built_in">dfs2</span>(v, u, v);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">Update</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> v, <span class="type">int</span> x)</span> </span>{</span><br><span class="line"> <span class="keyword">while</span>(top[u] != top[v]) {</span><br><span class="line"> <span class="keyword">if</span>(dep[top[u]] < dep[top[v]])</span><br><span class="line"> <span class="built_in">swap</span>(u, v);</span><br><span class="line"> <span class="built_in">update</span>(<span class="number">1</span>, <span class="number">1</span>, tot, id[top[u]], id[u], x);</span><br><span class="line"> u = ft[top[u]];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(dep[u] > dep[v])</span><br><span class="line"> <span class="built_in">swap</span>(u, v);</span><br><span class="line"> <span class="built_in">update</span>(<span class="number">1</span>, <span class="number">1</span>, tot, id[u], id[v], x);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">Query</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> v)</span> </span>{</span><br><span class="line"> <span class="type">int</span> s = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span>(top[u] != top[v]) {</span><br><span class="line"> <span class="keyword">if</span>(dep[top[u]] < dep[top[v]])</span><br><span class="line"> <span class="built_in">swap</span>(u, v);</span><br><span class="line"> s += <span class="built_in">query</span>(<span class="number">1</span>, <span class="number">1</span>, tot, id[top[u]], id[u]);</span><br><span class="line"> u = ft[top[u]];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(dep[u] > dep[v])</span><br><span class="line"> <span class="built_in">swap</span>(u, v);</span><br><span class="line"> <span class="keyword">return</span> s + <span class="built_in">query</span>(<span class="number">1</span>, <span class="number">1</span>, tot, id[u], id[v]);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">signed</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%lld %lld %lld %lld"</span>, &n, &q, &r, &mod);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%lld"</span>, &w[i]);</span><br><span class="line"> <span class="type">int</span> u, v;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">2</span>, n) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%lld %lld"</span>, &u, &v);</span><br><span class="line"> G[u].<span class="built_in">push_back</span>(v);</span><br><span class="line"> G[v].<span class="built_in">push_back</span>(u);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">dfs1</span>(r, <span class="number">0</span>);</span><br><span class="line"> <span class="built_in">dfs2</span>(r, <span class="number">0</span>, r);</span><br><span class="line"> <span class="built_in">build</span>(<span class="number">1</span>, <span class="number">1</span>, tot);</span><br><span class="line"> <span class="type">int</span> op, x, y, z;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, q) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%lld"</span>, &op);</span><br><span class="line"> <span class="keyword">if</span>(op == <span class="number">1</span>) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%lld %lld %lld"</span>, &x, &y, &z);</span><br><span class="line"> <span class="built_in">Update</span>(x, y, z);</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span>(op == <span class="number">2</span>) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%lld %lld"</span>, &x, &y);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%lld\n"</span>, <span class="built_in">Query</span>(x, y) % mod);</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span>(op == <span class="number">3</span>) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%lld %lld"</span>, &x, &y);</span><br><span class="line"> <span class="built_in">update</span>(<span class="number">1</span>, <span class="number">1</span>, tot, id[x], id[x] + sum[x] - <span class="number">1</span>, y);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%lld"</span>, &x);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%lld\n"</span>, <span class="built_in">query</span>(<span class="number">1</span>, <span class="number">1</span>, tot, id[x], id[x] + sum[x] - <span class="number">1</span>) % mod);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>变式:</p><ul><li><p><a href="https://loj.ac/problem/10138">「ZJOI2008」树的统计</a></p><p> 这个题目应该比板子简单,甚至都不需要区间修改,线段树维护一个结构体即可。敲代码的时候注意:</p><ol><li>注意检查线段树有没有挂。</li><li>节点权值有可能是负数。所以记得求最大值的时候把初始值赋为极小值。</li><li>打线段树的时候可以巧用运算符重载,比如我是这么写的: <figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> <span class="title class_">_</span> {</span><br><span class="line"> <span class="type">int</span> s, m;</span><br><span class="line"> _ <span class="keyword">operator</span>+(<span class="type">const</span> _ &x) <span class="type">const</span> { <span class="keyword">return</span> (_) { s + x.s, <span class="built_in">max</span>(m, x.m) }; }</span><br><span class="line">} t[maxn << <span class="number">2</span>], empty;</span><br></pre></td></tr></table></figure></li></ol></li><li><p><a href="https://loj.ac/problem/2125">「HAOI2015」树上操作</a></p><p> 几乎和模板一样,只是查询多了一个到根节点的询问,这个函数传参变一下就行了。当然,如果明确知道其中一个节点是根节点,树链剖分也可以这么写:</p> <figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">Update</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> k)</span> </span>{</span><br><span class="line"> <span class="keyword">while</span>(x) { <span class="comment">// 直接跳 x 即可,不用考虑根节点</span></span><br><span class="line"> <span class="built_in">update</span>(<span class="number">1</span>, <span class="number">1</span>, tot, id[top[x]], id[x], k);</span><br><span class="line"> x = ft[top[x]];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">Query</span><span class="params">(<span class="type">int</span> x)</span> </span>{</span><br><span class="line"> <span class="type">int</span> s = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span>(x) {</span><br><span class="line"> s += <span class="built_in">query</span>(<span class="number">1</span>, <span class="number">1</span>, tot, id[top[x]], id[x]);</span><br><span class="line"> x = ft[top[x]];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> s;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>啊对了,这题数组要开 <code>1e6</code> 而非 <code>1e5</code>,不然只有 $30$ 分,望周知。</p></li><li><p><a href="https://uoj.ac/problem/128">「NOI2015」软件包管理器</a></p><p>也是板子,不过需要一个转化。</p><p>最开始是一棵初始值全部为 $0$ 的树。</p><p><code>install</code> 操作:判断 $0\to u$ 路径上有多少个 $0$,并全部改为 $1$。可以再次转换:因为点权只有 $0/1$,故查询操作就是求 $dep_u-\text{query}(1\to u)$。</p><p><code>uninstall</code> 操作:判断 $u$ 的子树上有多少个 $1$,并全部改为 $0$。</p></li></ul>]]></content>
<summary type="html">一篇文章不长,代码占了一半。</summary>
<category term="学习笔记" scheme="https://blog.liynw.top/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<category term="树形结构" scheme="https://blog.liynw.top/tags/%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84/"/>
</entry>
<entry>
<title>最近公共祖先(LCA)</title>
<link href="https://blog.liynw.top/posts/d17dcd42/"/>
<id>https://blog.liynw.top/posts/d17dcd42/</id>
<published>2022-05-14T12:50:49.000Z</published>
<updated>2022-05-14T12:50:49.000Z</updated>
<content type="html"><![CDATA[<h2 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h2><blockquote><p>对于有根树 $T$ 的两个结点 $u,v$,它们的最近公共祖先(Lowest Common Ancestors)表示一个结点 $x$,满足 $x$ 是 $u$ 和 $v$ 的祖先且 $x$ 的深度尽可能大。在这里,一个节点也可以是它自己的祖先。</p></blockquote><p>LCA 可以求树上两个节点之间的最短路径。$dis(u,v)$ 其实就是 $u\to \text{lca}(u,v)\to v$。</p><p>写的是模板是因为一道题都没做出来。以后会补树上差分(</p><h2 id="倍增"><a href="#倍增" class="headerlink" title="倍增"></a>倍增</h2><p>这应该是最好理解的一种方法。</p><p>首先我们要知道暴力求 LCA 的方法:</p><ol><li>先把深度较大的那个节点往上跳,直到与另一个节点深度相同。</li><li>两个节点同时往上跳,直到两节点重合。这个重合的位置就是它们的 LCA。</li></ol><p>其实倍增的基本思路也是这个样子,但是与暴力不同的是,上述方法在节点往上跳的时候,是不断跳到它的父节点,也就是一个一个跳的。但是,为了追求速度,倍增 LCA 并没有一个一个地跳。</p><p>不知道大家还记得二进制拆分吗?任何一个整数,都可以拆成若干个 $2$ 的幂次相加的形式,且这些幂次互不相同。倍增 LCA 的思路也是这样的:任意一个节点到它 LCA 的距离肯定都是整数,所以一定可以拆出若干个互不相同的 $2$ 的幂次使得这些数的和是它。</p><p>以第二步为例,我们可以<strong>从大到小</strong>枚举 $k$:如果这两个节点往上跳 $2^k$ 之后还不能重合,那就说明 LCA 到它们的距离大于 $2^k$,跳上去了之后也不会错过 LCA,我们就直接把两个节点跳上去,然后接着枚举,直到两个节点可以重合。这个过程复杂度是 $\Theta(\log n)$。</p><p>第一步也是类似的,倍增地往上跳,直到两节点深度相同为止。</p><p>于是思路就想明白了。但是我们在往上跳的时候必须知道两个节点往上跳了一个距离之后会不会重合。所以需要预处理一下:$dp_{i,j}$ 代表 $i$ 节点上面的第 $2^j$ 个节点的编号。比如 $dp_{i,0}$ 就代表的是 $i$ 的父节点。</p><p>如何求解 $dp$ 数组呢?预处理打一个 DFS,有两个用处:</p><ol><li>求解每一个节点的深度。</li><li>求 $dp$ 数组。</li></ol><p>往下枚举的时候,我们知道一个节点的父节点是谁,实现起来传个参就行。假设 $v$ 的父节点是 $u$,那么先可以知道 $dp_{v,0}=u$。接着,用这个条件求出:$dp_{v,1}=dp_{u,0}$,也就是 $u$ 的父节点,假设这个节点是 $r$。然后就可以再求出:$dp_{v,2}=dp_{u,1}=dp_{r,0}$……推出通用的式子就是:</p><script type="math/tex; mode=display">\begin{cases} dp_{v,0}=u\\ dp_{v,k}=dp_{dp_{u,k-1},k-1}\ (k>0)\end{cases}</script><p>这应该相当于是一个树形 DP。</p><p>使用这个数组就很简单了,判断 $u,v$ 往上跳 $2^k$ 会不会重合就是判断 $dp_{u,k}$ 是否等于 $dp_{v,k}$。</p><p>参考代码:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><vector></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cmath></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>)<span class="number">2e4</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line">std::vector<<span class="type">int</span>> G[maxn];</span><br><span class="line"><span class="type">int</span> n, m, l, dep[maxn], dp[maxn][<span class="number">305</span>];</span><br><span class="line"><span class="type">bool</span> vis[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">swap</span><span class="params">(<span class="type">int</span> &x, <span class="type">int</span> &y)</span> </span>{ x ^= y, y ^= x, x ^= y; }</span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">LOG2F</span><span class="params">(<span class="type">int</span> x)</span> </span>{ <span class="keyword">return</span> (<span class="type">int</span>)<span class="built_in">log2</span>(x); } <span class="comment">// 求向下取整的 log2(n)</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> fa)</span> </span>{</span><br><span class="line"> <span class="type">int</span> len = G[u].<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) {</span><br><span class="line"> <span class="type">int</span> v = G[u][i];</span><br><span class="line"> <span class="keyword">if</span>(v != fa) {</span><br><span class="line"> dep[v] = dep[u] + <span class="number">1</span>;</span><br><span class="line"> dp[v][<span class="number">0</span>] = u;</span><br><span class="line"> <span class="built_in">rep</span>(k, <span class="number">1</span>, l)</span><br><span class="line"> dp[v][k] = dp[dp[v][k - <span class="number">1</span>]][k - <span class="number">1</span>];</span><br><span class="line"> <span class="built_in">dfs</span>(v, u);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">getLCA</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(dep[x] < dep[y])</span><br><span class="line"> <span class="built_in">swap</span>(x, y);</span><br><span class="line"> <span class="keyword">while</span>(dep[x] > dep[y])</span><br><span class="line"> x = dp[x][<span class="built_in">LOG2F</span>(dep[x] - dep[y])];</span><br><span class="line"> <span class="keyword">if</span>(x == y)</span><br><span class="line"> <span class="keyword">return</span> x;</span><br><span class="line"> <span class="built_in">dep</span>(k, <span class="built_in">LOG2F</span>(dep[x]), <span class="number">0</span>)</span><br><span class="line"> <span class="keyword">if</span>(dp[x][k] != dp[y][k])</span><br><span class="line"> x = dp[x][k], y = dp[y][k];</span><br><span class="line"> <span class="keyword">return</span> dp[x][<span class="number">0</span>];</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="type">int</span> root = <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n);</span><br><span class="line"> l = <span class="built_in">LOG2F</span>(n);</span><br><span class="line"> <span class="type">int</span> a, b, c;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d:(%d)"</span>, &a, &b);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, b) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &c);</span><br><span class="line"> vis[c] = <span class="number">1</span>;</span><br><span class="line"> G[a].<span class="built_in">push_back</span>(c);</span><br><span class="line"> G[c].<span class="built_in">push_back</span>(a);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> <span class="keyword">if</span>(!vis[i]) {</span><br><span class="line"> root = i;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> dep[root] = <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">dfs</span>(root, <span class="number">0</span>);</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &m);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, m) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &a, &b);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d\n"</span>, <span class="built_in">getLCA</span>(a, b));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="Tarjan-LCA"><a href="#Tarjan-LCA" class="headerlink" title="Tarjan LCA"></a>Tarjan LCA</h2><p>Tarjan 是一个人,他提出了很多牛逼的算法,比如说这个求 LCA 的算法,它可以在线性时间复杂度内求解若干个 LCA 的询问。当然,速度快是有代价的,Tarjan LCA 是离线算法,如果有强制在线就用不了了……</p><p>如果大家模拟过 DFS 一棵树的过程,就会发现,任意两个节点之间,DFS 遍历的路径肯定是这两个节点之间的最短路径!比如这个树:</p><p><img src="https://img-blog.csdnimg.cn/217867549295402a8be6d4b4b6c070a6.png" alt=""></p><p>它的遍历顺序就应该是:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1 2 4 9 4 2 5 10 5 11 5 2 6 2 1 3 7 3 8 3 1</span><br></pre></td></tr></table></figure><p>这个东西也就是我们说的<strong>欧拉序</strong>。</p><p>知道了最短路径其实也就知道 LCA 了,因为最短路径肯定经过 LCA。假如说我想求 $10$ 和 $6$ 的 LCA,我们就把第一个 $10$ 到第一个 $6$ 这一段截取出来(其实是第几个都无所谓,反正中间也不会出现比 $\text{lca}$ 深度更小的节点),也就是:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">10 5 11 5 2 6</span><br></pre></td></tr></table></figure><p>发现这一段深度最小的是节点是 $2$。所以 $\text{lca}(6,10)$ 就是 $2$。</p><p>这个思路衍生出了两种方法,第一种就是直接求用 ST 表求最小值,也就是下面介绍的第三种方法。但是 Tarjan 一看,不行,ST 表时间复杂度太大了,还有一种更快的办法。</p><p>我们一边 DFS,一边建立<strong>并查集</strong>,首先所有的待求节点都在不同的集合里。接着我们用一个数组 $col$ 代表这个节点有没有被遍历过。DFS 函数在遍历节点 $u$ 的时候都干了三件事:</p><ol><li>枚举 $u$ 所有子节点 $v$。每次先沿着 $v$ DFS 下去,然后再把 $v$ 所在的集合改为 $u$ 的集合。</li><li>标记 $u$ 已经被走过。</li><li>枚举所有询问,如果发现有某些组的询问<strong>一个节点是 $u$,另一个节点已经被遍历过</strong>,那这两个节点的 LCA 就是<strong>不是 $u$ 的那个点</strong>所在并查集的根。</li></ol><p>如何证明算法正确性?首先,遍历到 $u$ 的时候,被标记的节点一定不是 $u$ 的祖先节点,因为 $u$ 的祖先节点都没有回溯回去,不可能被标记。于是我们就知道了 $v$ 不可能是 $\text{lca}(u,v)$。其次,对于任意一个节点,总会先 DFS 下去,等回溯回来之后再让它加入其父节点的集合,所以,因为遍历过来的路程有一部分是 $v\to\text{lca}(u,v)\to u$,$v\to \text{lca}(u,v)$ 这一段所有节点都已经从下到上加入其父节点的集合,但是,从 $\text{lca}(u,v)$ 的父节点开始一直往上走到根节点那一段没有回溯回来,也就没有进行关于并查集的操作,所以 $v$ 所在集合的根节点显然就是在此集合中深度最小的 $\text{lca}(u,v)$。</p><p>参考代码:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><vector></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>)<span class="number">5e6</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, q, ans[maxn];</span><br><span class="line">std::vector<<span class="type">int</span>> G[maxn], Q[maxn], Q_id[maxn];</span><br><span class="line"><span class="type">bool</span> col[maxn];</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> fa[maxn];</span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">findset</span><span class="params">(<span class="type">int</span> x)</span> </span>{ <span class="keyword">return</span> x == fa[x] ? x : fa[x] = <span class="built_in">findset</span>(fa[x]); }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">tarjan</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> dad)</span> </span>{</span><br><span class="line"> <span class="type">int</span> len = G[u].<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) {</span><br><span class="line"> <span class="keyword">if</span>(G[u][i] != dad) {</span><br><span class="line"> <span class="built_in">tarjan</span>(G[u][i], u);</span><br><span class="line"> fa[G[u][i]] = u;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> col[u] = <span class="number">1</span>;</span><br><span class="line"> len = Q[u].<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) {</span><br><span class="line"> <span class="keyword">if</span>(col[Q[u][i]])</span><br><span class="line"> ans[Q_id[u][i]] = <span class="built_in">findset</span>(Q[u][i]);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &n, &q);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> fa[i] = i;</span><br><span class="line"> <span class="type">int</span> u, v;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n - <span class="number">1</span>) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &u, &v);</span><br><span class="line"> G[u].<span class="built_in">push_back</span>(v);</span><br><span class="line"> G[v].<span class="built_in">push_back</span>(u);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, q) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &u, &v);</span><br><span class="line"> Q[u].<span class="built_in">push_back</span>(v), Q_id[u].<span class="built_in">push_back</span>(i);</span><br><span class="line"> Q[v].<span class="built_in">push_back</span>(u), Q_id[v].<span class="built_in">push_back</span>(i);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">tarjan</span>(<span class="number">1</span>, <span class="number">0</span>);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, q)</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d\n"</span>, ans[i]);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="欧拉序-ST-表"><a href="#欧拉序-ST-表" class="headerlink" title="欧拉序 + ST 表"></a>欧拉序 + ST 表</h2><p>思路在上面讲过了。可以开一个数组 $pos$ 来记录每一个节点在 dfs 序中第一次出现的下标,这样就可以把求 $\text{lca}(u,v)$ 转换为求 $[pos_u,pos_v]$ 这一段深度最小的节点的权值。ST 表的实现可以使用结构体。</p><p>参考代码:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><vector></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cmath></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cctype></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>)<span class="number">1e6</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, q, root = <span class="number">1</span>, tot, dep[maxn], pos[maxn], dfn[maxn], ddep[maxn];</span><br><span class="line">std::vector<<span class="type">int</span>> G[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">read</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="type">int</span> x = <span class="number">0</span>, w = <span class="number">0</span>;</span><br><span class="line"> <span class="type">char</span> ch = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span>(!<span class="built_in">isdigit</span>(ch)) {</span><br><span class="line"> w |= ch == <span class="string">'-'</span>;</span><br><span class="line"> ch = <span class="built_in">getchar</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">while</span>(<span class="built_in">isdigit</span>(ch)) {</span><br><span class="line"> x = (x << <span class="number">3</span>) + (x << <span class="number">1</span>) + (ch ^ <span class="number">48</span>);</span><br><span class="line"> ch = <span class="built_in">getchar</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> w ? -x : x;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">write</span><span class="params">(<span class="type">int</span> x)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(x < <span class="number">0</span>) <span class="built_in">putchar</span>(<span class="string">'-'</span>), x = -x;</span><br><span class="line"> <span class="keyword">if</span>(x > <span class="number">9</span>) <span class="built_in">write</span>(x / <span class="number">10</span>);</span><br><span class="line"> <span class="built_in">putchar</span>(x % <span class="number">10</span> + <span class="string">'0'</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">RMQ</span> {</span><br><span class="line"> <span class="type">int</span> num, id;</span><br><span class="line"> <span class="keyword">friend</span> <span class="type">bool</span> <span class="keyword">operator</span><(RMQ x, RMQ y) { <span class="keyword">return</span> x.num < y.num; }</span><br><span class="line">} dp[maxn][<span class="number">35</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> RMQ <span class="title">min</span><span class="params">(RMQ x, RMQ y)</span> </span>{ <span class="keyword">return</span> x < y ? x : y; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">init</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, tot)</span><br><span class="line"> dp[i][<span class="number">0</span>].num = ddep[i], dp[i][<span class="number">0</span>].id = dfn[i];</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">1</span>; <span class="number">1</span> << j <= tot; ++j)</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i + (<span class="number">1</span> << (j - <span class="number">1</span>)) - <span class="number">1</span> <= tot; ++i)</span><br><span class="line"> dp[i][j] = <span class="built_in">min</span>(dp[i][j - <span class="number">1</span>], dp[i + (<span class="number">1</span> << (j - <span class="number">1</span>))][j - <span class="number">1</span>]);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> RMQ <span class="title">rmq</span><span class="params">(<span class="type">int</span> L, <span class="type">int</span> R)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(L > R)</span><br><span class="line"> L ^= R, R ^= L, L ^= R;</span><br><span class="line"> <span class="type">int</span> k = (<span class="type">int</span>)<span class="built_in">log2</span>(R - L + <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">min</span>(dp[L][k], dp[R - (<span class="number">1</span> << k) + <span class="number">1</span>][k]);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> fa)</span> </span>{</span><br><span class="line"> <span class="type">int</span> len = G[u].<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> dfn[++tot] = u;</span><br><span class="line"> pos[u] = tot;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) {</span><br><span class="line"> <span class="type">int</span> v = G[u][i];</span><br><span class="line"> <span class="keyword">if</span>(v != fa) {</span><br><span class="line"> dep[v] = dep[u] + <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">dfs</span>(v, u);</span><br><span class="line"> dfn[++tot] = u;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> n = <span class="built_in">read</span>(), q = <span class="built_in">read</span>();</span><br><span class="line"> <span class="type">int</span> x, y, ans = <span class="number">0</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n - <span class="number">1</span>) {</span><br><span class="line"> x = <span class="built_in">read</span>(), y = <span class="built_in">read</span>();</span><br><span class="line"> G[x].<span class="built_in">push_back</span>(y);</span><br><span class="line"> G[y].<span class="built_in">push_back</span>(x);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">dfs</span>(root, <span class="number">0</span>);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, tot)</span><br><span class="line"> ddep[i] = dep[dfn[i]];</span><br><span class="line"> <span class="built_in">init</span>();</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, q) {</span><br><span class="line"> x = <span class="built_in">read</span>(), y = <span class="built_in">read</span>();</span><br><span class="line"> ans = <span class="built_in">rmq</span>(pos[x ^ ans], pos[y ^ ans]).id;</span><br><span class="line"> <span class="built_in">write</span>(ans);</span><br><span class="line"> <span class="built_in">putchar</span>(<span class="string">'\n'</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="树链剖分"><a href="#树链剖分" class="headerlink" title="树链剖分"></a>树链剖分</h2><p>其实树剖求 LCA 思路跟倍增有点像,都是往上跳到 LCA 为止。但是两种方法的跳法不一样:倍增是利用二进制原理精准找到 LCA 的位置,树剖则是跳重链,直到两个节点在一条重链上。</p><p>在阅读以下内容之前,请确保您理解了<a href="/posts/534cd243/">关于树剖的基础内容</a>(概念及两个 DFS 函数)。</p><p>执行的操作也就是这样的,不断重复:</p><p>判断 $u,v$ 是否在一条重链上:</p><ul><li>若是,返回 $u,v$ 当中深度较小的那个节点。</li><li>若不是,就比较两个节点<strong>所在重链的链头的深度</strong>,把深度较大的那个节点跳到其重链链头的父节点。</li></ul><p>为什么不是直接比较两个节点的深度,而是要比较两个节点所在重链链头的深度呢?因为节点跳是跳到链头父节点,所以如果直接比较两节点深度,有可能跳上去了之后会错过 LCA。另外,跳到链头父节点的原因是需要换一条重链。</p><p>参考代码:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><vector></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cmath></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>)<span class="number">1e5</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line">std::vector<<span class="type">int</span>> G[maxn];</span><br><span class="line"><span class="type">int</span> n, m, dep[maxn], ft[maxn], sum[maxn], son[maxn], top[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs1</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> fa)</span> </span>{</span><br><span class="line"> ft[u] = fa;</span><br><span class="line"> <span class="type">int</span> len = G[u].<span class="built_in">size</span>() - <span class="number">1</span>, mx = <span class="number">0</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) {</span><br><span class="line"> <span class="type">int</span> v = G[u][i];</span><br><span class="line"> <span class="keyword">if</span>(v != fa) {</span><br><span class="line"> dep[v] = dep[u] + <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">dfs1</span>(v, u);</span><br><span class="line"> sum[u] += sum[v];</span><br><span class="line"> <span class="keyword">if</span>(sum[v] > mx) {</span><br><span class="line"> mx = sum[v];</span><br><span class="line"> son[u] = v;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> ++sum[u];</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs2</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> fa, <span class="type">int</span> tp)</span> </span>{</span><br><span class="line"> top[u] = tp;</span><br><span class="line"> <span class="type">int</span> len = G[u].<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) {</span><br><span class="line"> <span class="type">int</span> v = G[u][i];</span><br><span class="line"> <span class="keyword">if</span>(v != fa) {</span><br><span class="line"> <span class="keyword">if</span>(v == son[u])</span><br><span class="line"> <span class="built_in">dfs2</span>(v, u, tp);</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="built_in">dfs2</span>(v, u, v);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">getLCA</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{</span><br><span class="line"> <span class="keyword">while</span>(top[x] != top[y]) {</span><br><span class="line"> <span class="keyword">if</span>(dep[top[x]] < dep[top[y]])</span><br><span class="line"> y = ft[top[y]];</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> x = ft[top[x]];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> dep[x] < dep[y] ? x : y;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">dis</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <span class="keyword">return</span> dep[x] + dep[y] - (dep[<span class="built_in">getLCA</span>(x, y)] << <span class="number">1</span>); }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n);</span><br><span class="line"> <span class="type">int</span> a, b;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n - <span class="number">1</span>) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &a, &b);</span><br><span class="line"> G[a].<span class="built_in">push_back</span>(b);</span><br><span class="line"> G[b].<span class="built_in">push_back</span>(a);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">dfs1</span>(<span class="number">1</span>, <span class="number">0</span>);</span><br><span class="line"> <span class="built_in">dfs2</span>(<span class="number">1</span>, <span class="number">0</span>, <span class="number">1</span>);</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &m);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, m) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &a, &b);</span><br><span class="line"> <span class="keyword">if</span>(a == b)</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"0\n"</span>);</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d\n"</span>, <span class="built_in">dis</span>(a, b));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="对比"><a href="#对比" class="headerlink" title="对比"></a>对比</h2><p>设树有 $n$ 个节点,询问 $q$ 次,四种算法对比如下:</p><div class="table-container"><table><thead><tr><th style="text-align:center"></th><th style="text-align:center">倍增</th><th style="text-align:center">tarjan</th><th style="text-align:center">DFS 序 + ST 表</th><th style="text-align:center">树链剖分</th></tr></thead><tbody><tr><td style="text-align:center"><strong>时间复杂度</strong></td><td style="text-align:center">$\Theta((n+q)\log n)$</td><td style="text-align:center">$\Theta(n+q)$</td><td style="text-align:center">$\Theta(n+q+n\log n)$</td><td style="text-align:center">$\Theta(2n+q\log n)$</td></tr><tr><td style="text-align:center"><strong>离线/在线</strong></td><td style="text-align:center">在线</td><td style="text-align:center">离线</td><td style="text-align:center">在线</td><td style="text-align:center">在线</td></tr></tbody></table></div><p>(表格 From mjl 的 PPT)</p><p>可以发现,tarjan 的方法速度是最快的,所以在允许离线的时候建议使用,树剖的速度名列第二,如果需要在线的话它是最好的选择。</p>]]></content>
<summary type="html">介绍四种求 LCA 的方式</summary>
<category term="学习笔记" scheme="https://blog.liynw.top/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<category term="树形结构" scheme="https://blog.liynw.top/tags/%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84/"/>
</entry>
<entry>
<title>树形 DP</title>
<link href="https://blog.liynw.top/posts/c2587cc4/"/>
<id>https://blog.liynw.top/posts/c2587cc4/</id>
<published>2022-03-27T10:28:57.000Z</published>
<updated>2022-03-27T10:28:57.000Z</updated>
<content type="html"><![CDATA[<p>树形 DP,顾名思义,就是在树上的 DP。因为树是一个递归定义的概念,所以,树形 DP需要在 DFS 中进行,所以有人说树形 DP 是一种记忆化搜索。<del>(ZQW:没错就是我)</del></p><h2 id="树上背包"><a href="#树上背包" class="headerlink" title="树上背包"></a>树上背包</h2><p>这个类型的问题让我想起了背包问题中“有依赖的背包问题”,也就是说,这种背包问题的某些物品只有在选了前置物品的条件下才能选,具体的关系构成一棵树。</p><p>让我们来看一道例题:<a href="https://www.luogu.com.cn/problem/P2015">Luogu P2015 二叉苹果树</a>。</p><p>这道题有两个要求,第一个是必须保留 $Q$ 条边,第二个是要求留下的边的权值加起来最大。</p><p>因为树的任何一个节点都可以作为根节点,所以这里我们默认 $1$ 为根节点(下文同理)。</p><p>那么,跟普通背包一样,$dp$ 数组第一维代表抉择的物品,第二维代表背包容量,令 $dp_{u,j}$ 为根节点为 $u$ 的子树上保留 $j$ 条边能达到的最大权值和。</p><p>那该怎么状态转移呢?</p><p>首先,当我们求 $dp_{u,?}$ 的时候,肯定是要知道它所有子节点的答案。所以,<strong>DFS 向下递归的语句应该在状态转移语句的前面。</strong></p><p>其次,和普通背包一样,每一个物品(这里是每一条边)都有选和不选两种情况。只是这里,令 $u$ 的一个子节点为 $v$,假如 $(u,v)$ 这一条边没取,那以 $v$ 为根节点的这一棵子树都取不了了,所以只能忽略这棵子树,答案还是原来的 $dp_{u,i}$。而取的时候,情况就比较复杂了,我们需要考虑一下这棵子树到底要保留多少条,所以我们还需要一层循环 $k$,代表这棵子树上保留 $k$ 条边,$(u,v)$ 有一条边,所以剩下的所有子树加起来有 $j-k-1$ 条边。所以对于每一个子节点 $v$,状态转移方程如下:</p><script type="math/tex; mode=display">dp_{u,j}=\max_{k=j-1}^0\limits\{dp_{v,k}+dp_{u,j-k-1}+val_{u,v}\}</script><p>这里要注意:</p><ol><li>$k$ 到 $0$ 结束,$k=0$ 是不取的情况。</li><li>因为计算 $dp_{u,j}$ 时需要用到 $dp_{u,j-k-1}$ 的值,而 $dp_{j-k-1}$ 是<strong>其它子树上的最大权值之和</strong>,不能算上 $v$ 这一棵子树,所以 $j,k$ 枚举的顺序应该是倒着枚,以免重复(和 01 背包滚动数组背包容量要倒过来枚举是一样的道理)。</li></ol><p>代码如下:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><vector></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">node</span> {</span><br><span class="line"> <span class="type">int</span> to, val;</span><br><span class="line">};</span><br><span class="line"><span class="type">int</span> n, q, dp[<span class="number">105</span>][<span class="number">105</span>];</span><br><span class="line"><span class="type">bool</span> b[<span class="number">105</span>];</span><br><span class="line">std::vector<node> G[<span class="number">105</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">max</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <span class="keyword">return</span> x > y ? x : y; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> i)</span> </span>{</span><br><span class="line"> b[i] = <span class="number">1</span>;</span><br><span class="line"> <span class="type">int</span> len = G[i].<span class="built_in">size</span>();</span><br><span class="line"> <span class="keyword">if</span>(len == <span class="number">1</span>)</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> <span class="built_in">rep</span>(v, <span class="number">0</span>, len - <span class="number">1</span>) {</span><br><span class="line"> <span class="keyword">if</span>(!b[G[i][v].to]) {</span><br><span class="line"> <span class="built_in">dfs</span>(G[i][v].to);</span><br><span class="line"> <span class="built_in">dep</span>(j, q, <span class="number">0</span>)</span><br><span class="line"> <span class="built_in">dep</span>(k, j - <span class="number">1</span>, <span class="number">0</span>)</span><br><span class="line"> dp[i][j] = <span class="built_in">max</span>(dp[i][j], G[i][v].val + dp[G[i][v].to][k] + dp[i][j - k - <span class="number">1</span>]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &n, &q);</span><br><span class="line"> <span class="type">int</span> u, v, w;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n - <span class="number">1</span>) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d %d"</span>, &u, &v, &w);</span><br><span class="line"> G[u].<span class="built_in">push_back</span>(<span class="built_in">node</span>({v, w}));</span><br><span class="line"> G[v].<span class="built_in">push_back</span>(<span class="built_in">node</span>({u, w}));</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">dfs</span>(<span class="number">1</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d"</span>, dp[<span class="number">1</span>][q]);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><p>变式练习:</p><ul><li><p><a href="https://www.luogu.com.cn/problem/P2014">「CTSC1997」选课</a></p><p> 和例题基本上一样,只是这道题给的是一个森林而非一棵树。处理方法也很简单,只需要建一个 $0$ 号节点,把所有树的根节点连上去,然后以 $0$ 为根处理就行了。</p></li></ul><hr><h2 id="树的直径"><a href="#树的直径" class="headerlink" title="树的直径"></a>树的直径</h2><p>树的直径就是一棵树上最长的链,所以一棵树上可能不止一条直径。</p><h3 id="只求长度"><a href="#只求长度" class="headerlink" title="只求长度"></a>只求长度</h3><p>例题如下:</p><blockquote><p>如果一个数 $x$ 的约数和 $y$(不包括他本身)比他本身小,那么 $x$ 可以变成 $y$,$y$ 也可以变成 $x$。例如 $4$ 可以变为 $3$,$1$ 可以变为 $7$。限定所有数字变换在不超过 $n$ 的正整数范围内进行,求不断进行数字变换且不出现重复数字的最多变换步数。</p></blockquote><p>这道题转换挺巧妙的,该怎么看出来这是个求树的直径的问题呢?</p><p>其实,我们只需要画一张图,把数字作为节点,可以相互变换的数字连在一起就可以了:</p><p><img src="https://s2.loli.net/2022/03/19/fK1GaiWLA6Jse7Q.png" alt=""></p><p>这个时候就有人问了:那怎么证明这个图里没有环?</p><p>令对一个数 $a$ 求约数和的操作为 $f(a)$。假设 $f(x)=y,f(y)=z$,那如果想要构成一个环,就要求 $f(x)=z$,或者 $f(z)=x$。</p><p>第一种情况很好排除,因为只有 $y=z$ 时才能构成环,而 $f(y)=z$,所以,只有像 $6$ 那样的“完全数”才能满足。但是,既然 $y$ 已经是完全数了,那么说明 $x=y$,实际上这是一个自环,对结果没有影响,我们直接忽略掉它。</p><p>第二种情况乍一看不太好整,但是注意到题目要求可以发现 $x>y>z$,然后又要求 $f(z)<z$,很显然 $f(z)\neq x$。(所以第一种情况也可以直接排除了,因为完全数是不被允许的)</p><p>好的,现在我们可以证明这张图是一棵树了,接下来的事情就简单了。因为不能重复,所以我们只能从一个节点走到另一个节点不能回头,那只需要找到树上最长的链就行了,也就是树的直径。</p><p>那回归正题:怎么求树的直径的长度?</p><p>我们知道,一个节点上能产生的影响<strong>经过此节点的最长链</strong>的长度的链只有三条:</p><p><img src="https://s2.loli.net/2022/03/19/aS38NEZUgfYJx1D.png" alt=""></p><p>设节点 $u$ 往下的最长链长度为 $d1_u$,次长链为 $d2_u$,往上的链(经过它的父节点)为 $up_u$,那么这条链的长度要么是 $d1_u+d2_u$,要么是 $d1_u+up_u$,反正不可能是 $d2_u+up_u$(因为保证 $d1_u\ge d2_u$),所以我们可以发现是一定有 $d1_u$ 的。</p><p>那么,对于 $u$ 的所有父节点 $r$(这个 $r$ 指的不是某一个节点,而是所有 $u$ 的直系父节点,可以是它的爸爸,也可以是它的爷爷,一直往上追溯到根节点),$d1_u+up_u$ 和 $\max\{d1_r+d2_r\}$ 是一样的,因为后者其实包含了 $d1_u$ 和所有 $up_u$ 中的所有情况。这个大家自己画画图就知道了,用语言不太好描述 qwq。</p><p>所以,我们只需要遍历一下每一个节点的 $d1,d2$ 之和就可以了。</p><p>那 $d1,d2$ 该怎么求呢?</p><p>这就回归到了树形 DP。我们还是 DFS 往下找,遍历每一个节点 $u$ 的所有子节点 $v$。对于每一个子节点,先对它 DFS,此时每一个 $v$ 都有自己的 $d1_v$,我们只需要找到最大的两个 $d1_v$ ,再加上 $1$ 就可以求出 $d1_u$ 和 $d2_u$。</p><p>那为什么不能用 $d2_v$ 来更新呢?确实有这种情况:某个节点的最长链和次长链的下一个节点都在一个子节点上。但是我们的要求是:<strong>这两条链不能重合!</strong> 不然树的直径就经过重复的节点了,所以我们不能用 $d2_v$ 来更新 $d1_u$ 和 $d2_u$。</p><p>所以,光求长度跟 $up$ 数组没有半毛钱关系。</p><p>这道题的代码:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><vector></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cmath></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>)<span class="number">5e4</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, ans, h1[maxn], h2[maxn], q[maxn];</span><br><span class="line">std::vector<<span class="type">int</span>> G[maxn];</span><br><span class="line"><span class="type">bool</span> b[maxn];</span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">max</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <span class="keyword">return</span> x > y ? x : y; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">mk</span><span class="params">(<span class="type">int</span> x)</span> </span>{</span><br><span class="line"> <span class="type">int</span> s = <span class="number">0</span>, p = <span class="built_in">floor</span>(<span class="built_in">sqrt</span>(x));</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, p)</span><br><span class="line"> s += x % i ? <span class="number">0</span> : i + x / i;</span><br><span class="line"> <span class="keyword">if</span>(p * p == x)</span><br><span class="line"> s -= p;</span><br><span class="line"> <span class="keyword">return</span> s - x;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> u)</span> </span>{</span><br><span class="line"> b[u] = <span class="number">1</span>;</span><br><span class="line"> <span class="type">int</span> len = G[u].<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) {</span><br><span class="line"> <span class="type">int</span> v = G[u][i];</span><br><span class="line"> <span class="keyword">if</span>(!b[v]) {</span><br><span class="line"> <span class="built_in">dfs</span>(v);</span><br><span class="line"> <span class="keyword">if</span>(h1[v] + <span class="number">1</span> > h1[u]) {</span><br><span class="line"> h2[u] = h1[u];</span><br><span class="line"> h1[u] = h1[v] + <span class="number">1</span>;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span>(h1[v] + <span class="number">1</span> > h2[u])</span><br><span class="line"> h2[u] = h1[v] + <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> ans = <span class="built_in">max</span>(ans, h1[u] + h2[u]);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">2</span>, n)</span><br><span class="line"> q[i] = <span class="built_in">mk</span>(i);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">2</span>, n) {</span><br><span class="line"> <span class="keyword">if</span>(q[i] > i)</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> G[i].<span class="built_in">push_back</span>(q[i]);</span><br><span class="line"> <span class="keyword">if</span>(i != q[i])</span><br><span class="line"> G[q[i]].<span class="built_in">push_back</span>(i);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">/*</span></span><br><span class="line"><span class="comment"> rep(i, 1, n) {</span></span><br><span class="line"><span class="comment"> printf("%d: ", i);</span></span><br><span class="line"><span class="comment"> rep(j, 0, (int)G[i].size() - 1)</span></span><br><span class="line"><span class="comment"> printf("%d ", G[i][j]);</span></span><br><span class="line"><span class="comment"> printf("\n");</span></span><br><span class="line"><span class="comment"> }</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="built_in">dfs</span>(<span class="number">1</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d"</span>, ans);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><del>提交记录 #1145000。</del></p><hr><h3 id="求直径上的节点"><a href="#求直径上的节点" class="headerlink" title="求直径上的节点"></a>求直径上的节点</h3><p>来看上道题的加强版:要求我们输出所有在树的直径上的节点编号。</p><p>思路还是那个思路,不过这下我们就需要求 $up$ 了,这样我们才能知道每一个节点上的最长链到底等不等于树的直径的长度。</p><p>那怎么求某个节点 $u$ 的 $up$ 值呢?有两种情况:</p><ol><li>先从它父节点 $r$ 的 $up$ 值代表的路径走到 $r$,再走到 $u$,$up_u=up_r+1$;</li><li>先从 $r$ 的 $d1$ 值代表的路径走到 $r$,再走到 $u$,$up_u=d1_r+1$。</li></ol><p>过程就是这样吗?不完全是,请看图:</p><p><img src="https://img-blog.csdnimg.cn/a1efbdc1dc354a39beff28877b8a059c.png" alt=""></p><p>我们在更新 $up_4$ 的值时,会发现 $d1_2+1=4$,但是实际上很明显 $up_2=3$。这是因为 $d1_2$ 这一条路径会经过 $4$ 节点,而树的直径要求不能经过重复的节点,于是就出问题了。</p><p>解决方案是:当判断到 $d1_r$ 这条路径经过 $u$ 的时候,把 $d1_r+1$ 更换为 $d2_r+1$ 即可,如果 $d1_r$ 经过另外 $u$,那么 $d2_r$ 一定不经过 $u$。</p><p>输出答案时一个节点一个节点地判断,如果经过这个节点的最长链长度等于树的直径,那就输出。</p><p>代码如下(调了好久 qwq):</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><vector></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>)<span class="number">2e5</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, ans, d1[maxn], d2[maxn], up[maxn]; <span class="comment">// d1 为向下最长链,d2 为向下次长链,up 为第一步先到父节点之后不再折返回来的最长链 </span></span><br><span class="line">std::vector<<span class="type">int</span>> p, G[maxn]; <span class="comment">// G 存图,p 存答案 </span></span><br><span class="line"><span class="type">bool</span> b[maxn]; <span class="comment">// 标记走过的节点,以免重复走到 </span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">max</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <span class="keyword">return</span> x > y ? x : y; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs1</span><span class="params">(<span class="type">int</span> u)</span> </span>{ <span class="comment">// 从下往上递归,求解 d1, d2 和直径的长度 </span></span><br><span class="line"> b[u] = <span class="number">1</span>;</span><br><span class="line"> <span class="type">int</span> len = G[u].<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) { <span class="comment">// 遍历此节点的所有子节点 </span></span><br><span class="line"> <span class="type">int</span> v = G[u][i];</span><br><span class="line"> <span class="keyword">if</span>(!b[v]) {</span><br><span class="line"> <span class="built_in">dfs1</span>(v); </span><br><span class="line"> <span class="comment">// 用 d1[v] 去更新 d1[u] 和 d2[u]</span></span><br><span class="line"> <span class="comment">// ※注意不能用 d2[v]</span></span><br><span class="line"> <span class="keyword">if</span>(d1[v] + <span class="number">1</span> > d1[u]) {</span><br><span class="line"> d2[u] = d1[u];</span><br><span class="line"> d1[u] = d1[v] + <span class="number">1</span>;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span>(d1[v] + <span class="number">1</span> > d2[u])</span><br><span class="line"> d2[u] = d1[v] + <span class="number">1</span>;</span><br><span class="line"> ans = <span class="built_in">max</span>(ans, d1[u] + d2[u]); <span class="comment">// 更新最长链的长度,为了方便没有计算 u </span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs2</span><span class="params">(<span class="type">int</span> u)</span> </span>{ <span class="comment">// 从上往下递归,求解 up </span></span><br><span class="line"> b[u] = <span class="number">1</span>;</span><br><span class="line"> <span class="type">int</span> len = G[u].<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) {</span><br><span class="line"> <span class="type">int</span> v = G[u][i];</span><br><span class="line"> <span class="keyword">if</span>(!b[v]) {</span><br><span class="line"> <span class="keyword">if</span>(d1[v] + <span class="number">1</span> == d1[u]) <span class="comment">// 这说明 u 的最长链经过了 v,因为会重复走 v,所以不能用 d1 更新 up 而是应该用 d2 </span></span><br><span class="line"> up[v] = <span class="built_in">max</span>(up[u], d2[u]) + <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="comment">// 其余情况就正常更新 </span></span><br><span class="line"> up[v] = <span class="built_in">max</span>(up[u], d1[u]) + <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">dfs2</span>(v);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>; </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">void debug() {</span></span><br><span class="line"><span class="comment"> puts("--------------DEBUG--------------");</span></span><br><span class="line"><span class="comment"> printf("ans = %d\n", ans);</span></span><br><span class="line"><span class="comment"> printf("num d1 d2 up\n");</span></span><br><span class="line"><span class="comment"> rep(i, 1, n)</span></span><br><span class="line"><span class="comment"> printf("%-5d%-4d%-4d%-4d\n", i, d1[i], d2[i], up[i]);</span></span><br><span class="line"><span class="comment"> puts("---------------------------------\n");</span></span><br><span class="line"><span class="comment"> return;</span></span><br><span class="line"><span class="comment">}</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n);</span><br><span class="line"> <span class="type">int</span> u, v;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n - <span class="number">1</span>) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &u, &v);</span><br><span class="line"> ++u, ++v;</span><br><span class="line"> G[u].<span class="built_in">push_back</span>(v);</span><br><span class="line"> G[v].<span class="built_in">push_back</span>(u);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">dfs1</span>(<span class="number">1</span>);</span><br><span class="line"> <span class="built_in">memset</span>(b, <span class="number">0</span>, <span class="built_in">sizeof</span>(b));</span><br><span class="line"> <span class="built_in">dfs2</span>(<span class="number">1</span>);</span><br><span class="line"> <span class="comment">// debug();</span></span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> <span class="keyword">if</span>(d1[i] + <span class="built_in">max</span>(up[i], d2[i]) == ans) <span class="comment">// i 在最长链上</span></span><br><span class="line"> p.<span class="built_in">push_back</span>(i);</span><br><span class="line"> }</span><br><span class="line"> <span class="type">int</span> anslen = p.<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, anslen)</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d\n"</span>, p[i] - <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="与相邻节点有关的树形-DP"><a href="#与相邻节点有关的树形-DP" class="headerlink" title="与相邻节点有关的树形 DP"></a>与相邻节点有关的树形 DP</h2><p><del>实在不知道应该写什么名字才写的这个。</del></p><p>这种树形 DP 一般来说会有一维来记录此节点的状态(比如说要在树上染色,开一维代表这个节点有没有染色时候的状态)。</p><h3 id="例题-1"><a href="#例题-1" class="headerlink" title="例题 1"></a>例题 1</h3><p><a href="https://www.luogu.com.cn/problem/P2016">Luogu P2016 战略游戏</a></p><p>通过读题我们知道,当一条边的两个端点中有至少一个节点放了士兵,这条边就被监视了,所以可以定义 $dp_{u,0/1}$ 为把 $u$ 作为根节点时有/没有放士兵,<strong>而且这个子树上的所有边都被监视了</strong>的时候这课子树上能放的最少的士兵数量。</p><p>状态转移如下:</p><ul><li>$dp_{u,1}$:$u$ 已经放了士兵,所以它的子节点有没有放士兵都没有关系,方程是 $dp_{u,1}=\min\{dp_{v,0},dp_{v,1}\}$;</li><li>$dp_{u,0}$:$u$ 没放士兵,所以它的儿子必须自力更生,方程是 $dp_{u,0}=\min\{dp_{v,0}\}$。</li></ul><p>然后就没了。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = <span class="number">1505</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, dp[maxn][<span class="number">2</span>];</span><br><span class="line"><span class="type">bool</span> G[maxn][maxn], b[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">min</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <span class="keyword">return</span> x < y ? x : y; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> t)</span> </span>{</span><br><span class="line"> b[t] = <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> <span class="keyword">if</span>(G[t][i] && !b[i]) {</span><br><span class="line"> <span class="built_in">dfs</span>(i);</span><br><span class="line"> dp[t][<span class="number">0</span>] += dp[i][<span class="number">1</span>];</span><br><span class="line"> dp[t][<span class="number">1</span>] += <span class="built_in">min</span>(dp[i][<span class="number">0</span>], dp[i][<span class="number">1</span>]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> ++dp[t][<span class="number">1</span>];</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n);</span><br><span class="line"> <span class="type">int</span> u, v, s;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &u, &s);</span><br><span class="line"> ++u;</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">1</span>, s) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &v);</span><br><span class="line"> ++v;</span><br><span class="line"> G[u][v] = G[v][u] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">dfs</span>(<span class="number">1</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d"</span>, <span class="built_in">min</span>(dp[<span class="number">1</span>][<span class="number">0</span>], dp[<span class="number">1</span>][<span class="number">1</span>]));</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="例题-2"><a href="#例题-2" class="headerlink" title="例题 2"></a>例题 2</h3><p>基本上和例题 $1$ 一样,不过监视的对象从边换成了节点,然后每个节点安排士兵的时候都有一个输入给出的权值。</p><p>权值这个倒是没什么影响,但是从边变到节点,就出了一个问题,对于一个节点,只要它的儿子、它的父亲和它本身三者中有至少一个放了士兵,那这个节点就是合法的。所以,这道题的第二维有三种情况:</p><ul><li>$dp_{u,0}$ 代表 $u$ 节点自己就放了士兵,它的子节点 $v$ 不管状态是啥都是允许的,所以 $dp_{u,0}=\max{dp_{v,0},dp_{v,1},dp_{v,2}}$。</li><li>$dp_{u,1}$ 代表 $u$ 节点的父节点放了士兵,而它自己不放士兵,所以它的子节点就不能依靠父节点(也就是 $u$),$dp_{u,1}=\max\{dp_{v,0},dp_{v,2}\}$。</li><li>$dp_{u,2}$ 代表 $u$ 的至少一个子节点放了士兵,它自己不放。<strong>注意不是每个子结点都必须放,只需要有一个就行了,而且此时的子节点也不能依靠父节点。</strong> 所以 $dp_{u,2}$ 相较于 $dp_{u,1}$,只相差了一个子节点的贡献。我们通过一个循环找出一个子节点,使得它放了士兵和它没放士兵时相差的贡献值最小,这样就能保证 $dp_{u,2}$ 尽量接近 $dp_{u,1}$,也就是保障最优情况。方程是 $dp_{u,2}=dp_{u,1}-\min\{dp_{v,0},dp_{v,2}\}$。</li></ul><p>最后求答案的时候注意,根节点没有父节点,所以最终答案是 $\max\{dp_{1,0},dp_{1,2}\}$,没有 $dp_{1,1}$。</p><p>代码如下:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = <span class="number">1505</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, dp[maxn][<span class="number">3</span>], m[maxn];</span><br><span class="line"><span class="type">bool</span> G[maxn][maxn], b[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">min</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <span class="keyword">return</span> x < y ? x : y; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> u)</span> </span>{</span><br><span class="line"> b[u] = <span class="number">1</span>;</span><br><span class="line"> <span class="type">int</span> Min = <span class="number">1</span> << <span class="number">30</span>;</span><br><span class="line"> <span class="built_in">rep</span>(v, <span class="number">1</span>, n) {</span><br><span class="line"> <span class="keyword">if</span>(G[u][v] && !b[v]) {</span><br><span class="line"> <span class="built_in">dfs</span>(v);</span><br><span class="line"> dp[u][<span class="number">0</span>] += <span class="built_in">min</span>(dp[v][<span class="number">0</span>], <span class="built_in">min</span>(dp[v][<span class="number">1</span>], dp[v][<span class="number">2</span>]));</span><br><span class="line"> dp[u][<span class="number">1</span>] += <span class="built_in">min</span>(dp[v][<span class="number">0</span>], dp[v][<span class="number">2</span>]);</span><br><span class="line"> Min = <span class="built_in">min</span>(Min, dp[v][<span class="number">0</span>] - <span class="built_in">min</span>(dp[v][<span class="number">0</span>], dp[v][<span class="number">2</span>]));</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> dp[u][<span class="number">0</span>] += m[u];</span><br><span class="line"> dp[u][<span class="number">2</span>] = dp[u][<span class="number">1</span>] + Min;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n);</span><br><span class="line"> <span class="type">int</span> u, v, s, num;</span><br><span class="line"> <span class="keyword">if</span>(n == <span class="number">1</span>) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &u, &num);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d"</span>, num);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d %d"</span>, &u, &num, &s);</span><br><span class="line"> m[u] = num;</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">1</span>, s) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &v);</span><br><span class="line"> G[u][v] = G[v][u] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">dfs</span>(<span class="number">1</span>);</span><br><span class="line"> <span class="type">int</span> ans = <span class="built_in">min</span>(dp[<span class="number">1</span>][<span class="number">0</span>], dp[<span class="number">1</span>][<span class="number">2</span>]);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d"</span>, ans);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="例题-3"><a href="#例题-3" class="headerlink" title="例题 3"></a>例题 3</h3><p><a href="https://www.luogu.com.cn/problem/P1352">Luogu P1352 没有上司的舞会</a></p><p>对于一个人来说还是两种情况,要么就是他自己不来,要么就是他的上司不来。</p><ul><li>他来的话,他的所有部下都不能来。</li><li>他不来的话,他的部下既可以来也可以不来。</li></ul><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><vector></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = <span class="number">6005</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, p[maxn], dp[maxn][<span class="number">2</span>];</span><br><span class="line">std::vector<<span class="type">int</span>> G[maxn];</span><br><span class="line"><span class="type">bool</span> b[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">max</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span> </span>{ <span class="keyword">return</span> a > b ? a : b; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> u)</span> </span>{</span><br><span class="line"> b[u] = <span class="number">1</span>;</span><br><span class="line"> <span class="type">int</span> len = G[u].<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) {</span><br><span class="line"> <span class="type">int</span> v = G[u][i];</span><br><span class="line"> <span class="keyword">if</span>(!b[v]) {</span><br><span class="line"> <span class="built_in">dfs</span>(v);</span><br><span class="line"> dp[u][<span class="number">0</span>] += <span class="built_in">max</span>(dp[v][<span class="number">0</span>], dp[v][<span class="number">1</span>]);</span><br><span class="line"> dp[u][<span class="number">1</span>] += dp[v][<span class="number">0</span>];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> dp[u][<span class="number">1</span>] += p[u];</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &p[i]);</span><br><span class="line"> <span class="type">int</span> u, v;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n - <span class="number">1</span>) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &u, &v);</span><br><span class="line"> G[u].<span class="built_in">push_back</span>(v);</span><br><span class="line"> G[v].<span class="built_in">push_back</span>(u);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">dfs</span>(<span class="number">1</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d"</span>, <span class="built_in">max</span>(<span class="number">0</span>, <span class="built_in">max</span>(dp[<span class="number">1</span>][<span class="number">0</span>], dp[<span class="number">1</span>][<span class="number">1</span>])));</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="例题-4"><a href="#例题-4" class="headerlink" title="例题 4"></a>例题 4</h3><p><a href="https://www.luogu.com.cn/problem/P3155">「CQOI2009」叶子的染色</a></p><p>这题的题面说得很迷惑,其实你可以想象成拿一桶水,水最开始是无色的,从根节点往下流,最后流到叶子节点上,水的颜色遇到染色的节点就会变成节点的颜色(只有黑和白),但是这一股水颜色的变化只对以此节点为根的这棵子树有影响。要求确定每一个叶子节点收到的水的颜色,问你最少要让多少个节点染色。</p><p>$dp_{u.0/1}$ 代表经过 $u$ 节点的水流的颜色是黑/白时这棵子树上最少染色节点的数量。</p><p>我们先假设我们给 $u$ 的子节点 $v$ 染了色,所以最后需要加上 $1$。然后我们发现,如果水流经过 $u$ 和 $v$ 的颜色是一样的,那 $v$ 就可以不染色,所以在动规方程里,这种情况需要 $-1$。</p><p>叶子节点的初始化,颜色为 $c_u$ 时等于 $1$,不是 $c_u$ 的那一个设成极大值即可。</p><p>然后我们随便选一个非叶子节点作为根节点,把水倒下去就可以了。</p><p>代码:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><vector></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>)<span class="number">1e4</span> + <span class="number">5</span>;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> inf = <span class="number">1</span> << <span class="number">30</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m, ans, c[maxn], dp[maxn][<span class="number">2</span>];</span><br><span class="line">std::vector<<span class="type">int</span>> G[maxn];</span><br><span class="line"><span class="type">bool</span> b[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">min</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <span class="keyword">return</span> x < y ? x : y; }</span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">f</span><span class="params">(<span class="type">int</span> x)</span> </span>{ <span class="keyword">return</span> x ? <span class="number">0</span> : <span class="number">1</span>; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> u)</span> </span>{</span><br><span class="line"> b[u] = <span class="number">1</span>;</span><br><span class="line"> <span class="type">int</span> len = G[u].<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) {</span><br><span class="line"> <span class="type">int</span> v = G[u][i];</span><br><span class="line"> <span class="keyword">if</span>(!b[v]) {</span><br><span class="line"> <span class="built_in">dfs</span>(v);</span><br><span class="line"> dp[u][<span class="number">0</span>] += <span class="built_in">min</span>(dp[v][<span class="number">0</span>] - <span class="number">1</span>, dp[v][<span class="number">1</span>]);</span><br><span class="line"> dp[u][<span class="number">1</span>] += <span class="built_in">min</span>(dp[v][<span class="number">1</span>] - <span class="number">1</span>, dp[v][<span class="number">0</span>]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> ++dp[u][<span class="number">0</span>], ++dp[u][<span class="number">1</span>];</span><br><span class="line"> <span class="keyword">if</span>(u <= m) {</span><br><span class="line"> dp[u][c[u]] = <span class="number">1</span>;</span><br><span class="line"> dp[u][<span class="built_in">f</span>(c[u])] = inf;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &n, &m);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, m)</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &c[i]);</span><br><span class="line"> <span class="type">int</span> u, v;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n - <span class="number">1</span>) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &u, &v);</span><br><span class="line"> G[u].<span class="built_in">push_back</span>(v);</span><br><span class="line"> G[v].<span class="built_in">push_back</span>(u);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">dfs</span>(m + <span class="number">1</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d"</span>, <span class="built_in">min</span>(dp[m + <span class="number">1</span>][<span class="number">0</span>], dp[m + <span class="number">1</span>][<span class="number">1</span>]));</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="例题-5"><a href="#例题-5" class="headerlink" title="例题 5"></a>例题 5</h3><p><a href="https://www.luogu.com.cn/problem/P2279">「HNOI2003」消防局的设立</a></p><p><del>人类在 2003 年许下的美好愿望,到了 2020 年终于是没实现。</del></p><p>这题乍一看跟例 $2$ 好像也没啥区别是吧?</p><p>怎么可能!虽然保管的距离只是从 $1$ 变成了 $2$,但是要麻烦多了。</p><p>这题有两种做法,一个是树形 DP,有五种状态(它爷爷,它爸爸,它自己,它儿子,它孙子),<del>因为笔者不会,所以</del>请大家自行推导;还有一种就是今天要介绍的贪心方法,这个贪心的策略浓缩成一句话就是:<strong>从下往上找,如果不满足条件,就在这里修一个消防站。</strong></p><p>首先 DFS 预处理每一个节点的深度,然后再按照深度从大到小排序。注意这里因为要排序,所以记录节点深度的数组 $deep$ 应该是一个结构体,分别存深度大小和是哪一个节点。</p><p>我们需要两个数组,一个是 $q$,$q_u$ 代表排完序之后 $u$ 这个节点和它的深度在 $deep$ 数组的位置(下标,这个数组是为了方便寻找某个节点的父节点,这样可以直接找到某个节点的深度),另一个是 $data$,$data_u$ 代表现在离 $u$ 最近的一个消防站有多远。</p><p>按照深度从大到小枚举节点,然后判断这个节点有没有被消防站覆盖,如果没有就盖一个,顺便更新一下它父亲和爷爷的 $data$ 值。</p><p>然后就没了。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><vector></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><algorithm></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">node</span> {</span><br><span class="line"> <span class="type">int</span> num, id;</span><br><span class="line">} deep[<span class="number">1005</span>];</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, ans, data[<span class="number">1005</span>], q[<span class="number">1005</span>];</span><br><span class="line">std::vector<<span class="type">int</span>> G[<span class="number">1005</span>];</span><br><span class="line"><span class="type">bool</span> b[<span class="number">1005</span>], build[<span class="number">1005</span>];</span><br><span class="line"></span><br><span class="line"><span class="type">bool</span> <span class="keyword">operator</span><(node x, node y) { <span class="keyword">return</span> x.num > y.num; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">min</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <span class="keyword">return</span> x < y ? x : y; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">getdeep</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> dep)</span> </span>{</span><br><span class="line"> b[u] = <span class="number">1</span>;</span><br><span class="line"> <span class="type">int</span> len = G[u].<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) {</span><br><span class="line"> <span class="type">int</span> v = G[u][i];</span><br><span class="line"> <span class="keyword">if</span>(!b[v])</span><br><span class="line"> <span class="built_in">getdeep</span>(v, dep + <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> deep[u].id = u;</span><br><span class="line"> deep[u].num = dep;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">fa</span><span class="params">(<span class="type">int</span> u)</span> </span>{ <span class="comment">// 找 u 的父亲</span></span><br><span class="line"> <span class="type">int</span> len = G[u].<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) {</span><br><span class="line"> <span class="type">int</span> v = G[u][i];</span><br><span class="line"> <span class="keyword">if</span>(deep[q[v]].num == deep[q[u]].num - <span class="number">1</span>)</span><br><span class="line"> <span class="keyword">return</span> v;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">memset</span>(data, <span class="number">0x3f3f3f</span>, <span class="built_in">sizeof</span>(data));</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n);</span><br><span class="line"> <span class="type">int</span> v;</span><br><span class="line"> <span class="built_in">rep</span>(u, <span class="number">2</span>, n) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &v);</span><br><span class="line"> G[u].<span class="built_in">push_back</span>(v);</span><br><span class="line"> G[v].<span class="built_in">push_back</span>(u);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">getdeep</span>(<span class="number">1</span>, <span class="number">0</span>);</span><br><span class="line"> std::<span class="built_in">stable_sort</span>(deep + <span class="number">1</span>, deep + n + <span class="number">1</span>);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> q[deep[i].id] = i;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) { </span><br><span class="line"> <span class="comment">// *需要注意,这个循环里面我们要判断修不修消防站的是 gf 节点,所以我们需要知道它两代及以内的所有节点,即 u, ft, ggf, gggf</span></span><br><span class="line"> <span class="type">int</span> ft = <span class="built_in">fa</span>(deep[i].id);</span><br><span class="line"> <span class="type">int</span> gf = <span class="built_in">fa</span>(ft);</span><br><span class="line"> <span class="keyword">if</span>(!build[ft] && !build[gf] && data[deep[i].id] > <span class="number">2</span> && data[ft] > <span class="number">1</span> && data[gf] > <span class="number">0</span>) {</span><br><span class="line"> ++ans;</span><br><span class="line"> <span class="comment">// printf("%d: build %d\n", deep[i].id, gf);</span></span><br><span class="line"> build[gf] = <span class="number">1</span>;</span><br><span class="line"> data[deep[i].id] = <span class="built_in">min</span>(data[deep[i].id], <span class="number">0</span>);</span><br><span class="line"> <span class="type">int</span> ggf = <span class="built_in">fa</span>(gf);</span><br><span class="line"> <span class="type">int</span> gggf = <span class="built_in">fa</span>(ggf);</span><br><span class="line"> data[ggf] = <span class="built_in">min</span>(data[ggf], <span class="number">1</span>);</span><br><span class="line"> data[gggf] = <span class="built_in">min</span>(data[gggf], <span class="number">2</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d"</span>, ans);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h2 id="换根-DP"><a href="#换根-DP" class="headerlink" title="换根 DP"></a>换根 DP</h2><p>换根 DP,就是在求解的过程中以不同的节点为根来求解问题。</p><p>看例题:<a href="https://www.luogu.com.cn/problem/P3478">Luogu P3478 STA-Station</a>。</p><p>求解这个问题需要知道以每个节点为根时的深度总和,但是我们不可能每一个节点都 DFS 一次,这样就超时了。但是,有没有方法可以只 DFS 一个节点,然后根据这个节点的答案去求解其它节点的答案?</p><p><img src="https://s2.loli.net/2022/03/12/93xVLqbsACiFyPT.png" alt=""></p><p>这张图是我们把根节点从 $2$ 转移到 $4$ 的过程。可以发现,在 $4$ 为根节点时,以 $2$ 为根节点的子树(红色框)所有节点到根节点的距离都会加上 $w$;而在 $2$ 为根节点时,以 $4$ 为根节点的子树(蓝色框)所有节点到根节点的距离都会减少 $w$,只要知道两棵子树分别有多少个节点,就可以根据 $2$ 的答案求解出 $4$ 的答案,公式是 $ans_4=ans_2+size(red)\times w-size(blue)\times w$。</p><p>所以,我们可以先打一个预处理的 DFS 函数,把以 $1$ 为根节点时每一棵子树的节点总量都求出来。设 $num_i$ 为以 $1$ 为根节点,子树根节点为 $i$ 时这棵子树节点的数量。</p><p>当然,在实际求解的时候,因为求解过程中转移时的根节点不一定是 $1$,但是某个子树(假设根节点为 $u$)里面包含我们预处理时的根节点 $1$。所以这个子树的节点总数就不能直接用 $num_u$,而应该用 $n-num_v$($v$ 为 $u$ 的另一个子节点,以上图举例,$u=2,v=4$)。</p><p>然后就是代码了:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><vector></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> int long long</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>)<span class="number">1e6</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, ans, p, deepsum[maxn], num[maxn];</span><br><span class="line"><span class="type">bool</span> b[maxn];</span><br><span class="line">std::vector<<span class="type">int</span>> G[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">min</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <span class="keyword">return</span> x < y ? x : y; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs1</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> s)</span> </span>{ <span class="comment">// 预处理</span></span><br><span class="line"> b[u] = <span class="number">1</span>;</span><br><span class="line"> <span class="type">int</span> len = G[u].<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) {</span><br><span class="line"> <span class="type">int</span> v = G[u][i];</span><br><span class="line"> <span class="keyword">if</span>(!b[v]) {</span><br><span class="line"> <span class="built_in">dfs1</span>(v, s + <span class="number">1</span>);</span><br><span class="line"> deepsum[u] += deepsum[v];</span><br><span class="line"> num[u] += num[v];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> deepsum[u] += s;</span><br><span class="line"> ++num[u];</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs2</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> Num)</span> </span>{ <span class="comment">// 换根 DP</span></span><br><span class="line"> b[u] = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span>(ans < Num) {</span><br><span class="line"> ans = Num;</span><br><span class="line"> p = u;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span>(ans == Num)</span><br><span class="line"> p = <span class="built_in">min</span>(u, p);</span><br><span class="line"> <span class="type">int</span> len = G[u].<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, len) {</span><br><span class="line"> <span class="type">int</span> v = G[u][i];</span><br><span class="line"> <span class="keyword">if</span>(!b[v])</span><br><span class="line"> <span class="built_in">dfs2</span>(v, Num + n - (num[v] << <span class="number">1</span>));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">signed</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%lld"</span>, &n);</span><br><span class="line"> <span class="type">int</span> u, v;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n - <span class="number">1</span>) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%lld %lld"</span>, &u, &v);</span><br><span class="line"> G[u].<span class="built_in">push_back</span>(v);</span><br><span class="line"> G[v].<span class="built_in">push_back</span>(u);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">dfs1</span>(<span class="number">1</span>, <span class="number">0</span>);</span><br><span class="line"> <span class="built_in">memset</span>(b, <span class="number">0</span>, <span class="built_in">sizeof</span>(b));</span><br><span class="line"> ans = deepsum[<span class="number">1</span>];</span><br><span class="line"> p = <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">dfs2</span>(<span class="number">1</span>, deepsum[<span class="number">1</span>]);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%lld"</span>, p);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><p>变式:</p><ul><li><p><a href="https://www.luogu.com.cn/problem/P2986">「USACO10MAR」Great Cow Gathering G</a></p><p> 几乎和例题是一样的,不一样之处在于,这道题的边是有权值的。那么,“节点的深度”就要变成“节点到根节点的距离”,其实也没什么大改动,代码就不放了。</p></li></ul><hr><h2 id="其它"><a href="#其它" class="headerlink" title="其它"></a>其它</h2><ul><li><p>一道树上的区间 DP:<a href="https://www.luogu.com.cn/problem/P1040">「NOIP2003 TG」加分二叉树</a></p><p> 这题的突破点在于数的中序遍历必须是 $1,2,3,\ldots,n$,也就是说,一段连续的区间内的节点一定是在一块儿的,而且如果我们选定节点 $i$ 为 $[l,r]$ 这个区间的根节点,那么 $[l,i-1]$ 就是它的左子树,$[i+1,r]$ 就是它的右子树。</p><p> 然后三重循环的区间 DP 就来了:令区间 $[l,r]$ 是<strong>一棵子树</strong>(而不是分散的),在区间范围内枚举这个子树的根节点为 $k$,根据题目给出的公式计算出能得到的最大加分。</p><p> 另外,由于枚举时计算左右子树是 $[l,k-1]$ 和 $[k+1,r]$,所有有可能出现左端点比右端点还大的情况,其实这种情况就是空子树。我们可以在初始化的时候把 $dp_{i,i-1}$ 的值设为 $1$ 来解决这个问题。</p><p> 输出方案的话,可以用 $f_{i,j}$ 来存把区间 $[i,j]$ 作为一棵子树时的根节点,然后再按照前序遍历的方法“根——左——右”递归输出。</p><p> 贴一下代码:</p> <figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"> </span><br><span class="line"><span class="type">int</span> n, p[<span class="number">35</span>], dp[<span class="number">35</span>][<span class="number">35</span>], f[<span class="number">35</span>][<span class="number">35</span>];</span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">print</span><span class="params">(<span class="type">int</span> l, <span class="type">int</span> r)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(l > r)</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d "</span>, f[l][r]);</span><br><span class="line"> <span class="built_in">print</span>(l, f[l][r] - <span class="number">1</span>);</span><br><span class="line"> <span class="built_in">print</span>(f[l][r] + <span class="number">1</span>, r);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &p[i]);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> dp[i][i] = p[i], f[i][i] = i;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, n)</span><br><span class="line"> dp[i + <span class="number">1</span>][i] = <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(len, <span class="number">2</span>, n) {</span><br><span class="line"> <span class="built_in">rep</span>(l, <span class="number">1</span>, n - len + <span class="number">1</span>) {</span><br><span class="line"> <span class="type">int</span> r = l + len - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(k, l, r) {</span><br><span class="line"> <span class="type">int</span> w = dp[l][k - <span class="number">1</span>] * dp[k + <span class="number">1</span>][r] + p[k];</span><br><span class="line"> <span class="keyword">if</span>(w > dp[l][r]) {</span><br><span class="line"> dp[l][r] = w;</span><br><span class="line"> f[l][r] = k;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d\n"</span>, dp[<span class="number">1</span>][n]);</span><br><span class="line"> <span class="built_in">print</span>(<span class="number">1</span>, n);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul>]]></content>
<summary type="html">完结撒花 qwq</summary>
<category term="学习笔记" scheme="https://blog.liynw.top/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<category term="动态规划" scheme="https://blog.liynw.top/tags/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/"/>
</entry>
<entry>
<title>状压 DP 总结 & 练习简要题解</title>
<link href="https://blog.liynw.top/posts/f8e3c54/"/>
<id>https://blog.liynw.top/posts/f8e3c54/</id>
<published>2022-01-26T23:00:54.000Z</published>
<updated>2022-02-01T10:18:50.000Z</updated>
<content type="html"><![CDATA[<h2 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h2><p>状压 DP 就是状态压缩 DP,表现为把某一些状态(比如说某个元素是否被取过)压缩成二进制(当然也有别的进制),用这个进制下某个数的表示来表示一个状态,然后把这个状态作为 $dp$ 数组的一维来状态转移。</p><p>比如说有 $5$ 个元素,$1,2,4$ 已经被取过,$3,5$ 还没有。可以用如下二进制数来表示:</p><script type="math/tex; mode=display">(11010)_2=(26)_{10}</script><p>那么 $dp$ 数组就可以开一维来记录状态,当这一维的下标为 $26$ 时,就代表这个状态。<del>所以状压题的数据范围非常的明显,当然,这种数据范围也不排除暴搜的可能性。</del></p><p><del>对,总结就这么点。</del> 其实做状压 DP 就是不停地做题。</p><hr><h2 id="练习题目记录(怎么错的)"><a href="#练习题目记录(怎么错的)" class="headerlink" title="练习题目记录(怎么错的)"></a>练习题目记录(怎么错的)</h2><p>因为蒟蒻 ljt 做状压每一道都要调很久很久,所以 ta 决定把这些玩意儿记录下来。</p><p>当然这个东西是写给自己看的,所以写得比较混乱,如果您需要且看不懂的话可以问我 qwq。<del>当然肯定是没人需要的。</del></p><p>A. 牧场的安排</p><ul><li>$\text{82pts}$ 初始化了第一行,结果没考虑到数据只有一行的情况。</li></ul><p>B. 最小总代价</p><ul><li>$\text{0pts}$ 题意理解错了又没看样例。</li><li>$\text{95pts}$ <code>(1 << N) - 1</code> 误打成了 <code>(1 << N + 1) - 1</code>(忘改过来了)。</li></ul><p>C. 项链</p><ul><li>$\text{0pts}$ 四重循环被老爷机制裁了。</li><li>$\text{10pts}$ 比较玄学,把范围改成 $0\sim n-1$ 就过了。</li></ul><p>D. 国王</p><ul><li>$\text{0pts}$ <code>num(y)</code> 误打成了 <code>num(x)</code>(记得分清楚每个变量的意义!)。</li></ul><p>E. Hie with the Pie</p><ul><li>$\text{0pts}$ 没有理解做法,Floyd 的用处。</li><li>$\text{15pts}$ 没加多组数据。</li></ul><p>F. Traveling</p><ul><li>$\text{0pts}$ 锅太多了,主要有以下几个:<ul><li>预处理错误,没有真正弄明白预处理数组的意义。</li><li>循环顺序错误,枚举状态应该写在在最外面。</li><li>你没事加什么并查集啊!</li><li>数组两维大小不一样,开反了。</li></ul></li></ul><p>H. 炮兵阵地</p><ul><li>$\text{0pts}$ 运算符优先级的问题,众所周知 <code>+</code> 优先级比三目运算符高。 /yiw</li><li>$\text{40pts}$ 数组开小了。</li></ul><p>O. 集合选数</p><ul><li>$\text{0pts}$ 把加法原理和乘法原理弄混。</li><li>$\text{30pts}$ 构造矩阵的问题,$o$ 只需要乘一遍就可以了,我多乘了一遍,没有去重。</li><li>$\text{60pts}$ <code>memset</code> 速度过慢。</li><li>$\text{90pts}$ 打表出奇迹!</li></ul><hr><h2 id="简要题解"><a href="#简要题解" class="headerlink" title="简要题解"></a>简要题解</h2><h3 id="A-牧场的安排"><a href="#A-牧场的安排" class="headerlink" title="A. 牧场的安排"></a>A. 牧场的安排</h3><blockquote><p>题意:有一个 $N\times M$ 的矩阵,有些格子里面可以种草,但是不能有相邻的格子同时种草(相邻指上下左右)。给出一个矩阵 $a$,$a_{i,j}=1/0$ 代表 $i$ 行 $j$ 列的格子可以/不可以种草。求种草的方案总数,答案需要 $\bmod\ 10^8$。$1\le N,M\le 12$。</p></blockquote><p>$dp_{i,j}$ 代表前 $i$ 行,最后一行状态为 $j$ 时的方案数量。其中 $j$ 是一个二进制数,<strong>从高位到低位</strong>编号为 $1,2,3,\ldots$ 分别代表第 $1,2,3,\ldots$ 块地种不种草,$1$ 代表种了,$0$ 代表没种。</p><p>然后每枚举到某一行的某个状态时,在这个状态下,我们需要知道三件事:</p><ol><li>这一行的状态有相邻的格子种草吗?</li><li>这一行和上一行有相邻的格子种草吗?</li><li>这一行是否有一些格子本来不能种草却被种上了?</li></ol><p>只有这三个问题的回答都是“不”,这个状态才是合法的。</p><p>要知道这三个问题的答案,我们还需要知道上一行的状态(回答第二个问题和状态转移)。所以可以再打一层循环枚举上一层的状态。那如何判断这三个问题呢?使用位运算就可以了。</p><p>首先看第一个,要判断一个二进制数当中是否有相邻的 $1$。我们知道按位与可以找到两个数同一个位置上同时存在的 $1$,那我们换个思考方向,如果把这个数本身左移或者右移一位呢?此时这两个数要是再按位与之后结果还是不为 $0$,那么就说明这两个数至少有一个地方有同一个位置上同时存在 $1$。而因为其中一个数是由另一个数左移/右移过来的,也就是说明至少有一个位置上的 $1$ 左边/右边有一个相邻的 $1$,也就是说有两个 $1$ 相邻,则不符合条件。</p><p>举个例子:<code>100101100101</code></p><p>左移一位后按位与:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"> 100101100101</span><br><span class="line">100101100101</span><br><span class="line">--------------</span><br><span class="line">0000001000000</span><br></pre></td></tr></table></figure><p>可以看到结果不为 $0$,则说明这个状态是不合法的。实际上,确实有两个 $1$ 连在一起了。</p><p>再来看第二个。要判断两个数是否有同一个位置上同时存在 $1$,这个很简单,甚至不需要任何处理,直接把两个数按位与一下即可,要是结果不为 $0$ 则代表状态不合法。</p><p>最后看第三个。其实我们检查的是<strong>一个二进制数的 $\textbf{1}$ 的集合是否完全包含另一个二进制数的 $\textbf{1}$ 的集合</strong>(这里的“集合”是指 $1$ 的位置的集合)。那么我们可以把两个数按位或,再检查按位或之后的结果是否等于集合范围更大的那个数。如果不相等,则代表大集合不能完全包含小集合,不合法。(思考一下,为什么?)</p><p>确定好了三个条件之后,我们终于可以愉快地转移状态了。</p><script type="math/tex; mode=display">dp_{i,j}=\sum\limits_{k=0}^{2^n-1}dp_{i-1,k}</script><p>(当然计算和的时候要满足三个条件了才能加。)</p><p>初始化 $dp_{0,0}=1$。<del>个人觉得状压 DP 的初始化是个很玄学的东西。</del></p><p>时间复杂度 $\Theta(n2^n)$。</p><p>Code:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = <span class="number">5101</span>, mod = (<span class="type">int</span>)<span class="number">1e8</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m, N, x, ans, num[<span class="number">15</span>], dp[<span class="number">15</span>][maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &n, &m);</span><br><span class="line"> N = (<span class="number">1</span> << m) - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">1</span>, m) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &x);</span><br><span class="line"> num[i] = (num[i] << <span class="number">1</span>) + x; <span class="comment">// 把给出的矩阵转换成 n 个二进制数方便判断</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> dp[<span class="number">0</span>][<span class="number">0</span>] = <span class="number">1</span>; <span class="comment">// 初始化</span></span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) { <span class="comment">// 第 i 行</span></span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">0</span>, N) { <span class="comment">// 第 i 行的状态</span></span><br><span class="line"> <span class="keyword">if</span>(j & (j << <span class="number">1</span>) || (j | num[i]) ^ num[i]) <span class="comment">// 这里想写成 != 也可以,想写成异或也行,看大家的习惯咯</span></span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> <span class="built_in">rep</span>(k, <span class="number">0</span>, N) { <span class="comment">// 第 i-1 行的状态</span></span><br><span class="line"> <span class="keyword">if</span>(!(k & j))</span><br><span class="line"> dp[i][j] = (dp[i][j] + dp[i - <span class="number">1</span>][k]) % mod; <span class="comment">// 状态转移</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(i == n)</span><br><span class="line"> ans = (ans + dp[i][j]) % mod; <span class="comment">// 计算答案,也可以拎出来单独写循环</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d"</span>, ans);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h3 id="B-最小总代价"><a href="#B-最小总代价" class="headerlink" title="B. 最小总代价"></a>B. 最小总代价</h3><blockquote><p>题意:$n$ 个人传物品,从任意一个人开始,每个人只能接一次物品。每两个人之间传物品都要付出一定的代价,求把物品传给所有的人的最小代价和。$2\le n\le 16$。</p></blockquote><p>PS. 这道题我写的是 $\Theta(n^22^n)$,但其实有更优的 $\Theta(n2^n)$ 算法。不过没关系,因为状压的解题思路都差不多,那种思路我会在后面介绍,所以也可以看一看我当初的想法。</p><p>$dp_{i,j,k}$ 表示目前传到的人数的个数为 $i$,状态为 $j$(从<strong>低位往高位数</strong>第 $i$ 位代表第 $i$ 个人是否已经被传到),且东西是第 $k$ 个人给出的(给谁了不知道)时的最小代价和。<del>所以很明显这个 $i$ 是不需要的 qwq。</del></p><blockquote><p>这里注意一下,上一道题是从高位到低位,这道题是从低位到高位,这是题目给法不一样造成的结果。上一道题题目是直接给出了我们需要使用的矩阵,那么从左往右遍历比较方便,而这道题我们需要知道在传递之前到传递之后状态的变化(而不是通过枚举得到两个状态,详情见后文),所以左移多少位肯定是从低位往高位写比较舒服。不管怎么样,我们写代码都是为了思考方便、写起来方便而定义的,当然如果两样都需要,我们就要考虑考虑如何处理这个冲突了。</p></blockquote><p>在转移的时候,还需要加一层循环,枚举是谁收到了 $k$ 给的物品,这样才可以确定加上的代价。</p><p>至于转移过程中还有一些剪枝或者判断,只有合法的情况才能继续下一层循环。这个过程可以看代码。</p><p>转移状态:</p><script type="math/tex; mode=display">dp_{i,j|2^{k-1},k}=\min\limits_{l=1}^{n}\{dp_{i-1,j,l}+a_{k,l}\}</script><p>初始化 $dp$ 极大值,$dp_{1,0\sim 2^n-1,1\sim n}=0$。</p><p>Code:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="number">1</span> << <span class="number">16</span>) + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">min</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <span class="keyword">return</span> x < y ? x : y; }</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, N, ans = <span class="number">1</span> << <span class="number">30</span>, a[<span class="number">20</span>][<span class="number">20</span>], dp[<span class="number">20</span>][maxn][<span class="number">20</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">num</span><span class="params">(<span class="type">int</span> x)</span> </span>{ <span class="comment">// 这个函数用来统计一个数的二进制中有多少个 1</span></span><br><span class="line"> <span class="type">int</span> s = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span>(x) {</span><br><span class="line"> s += (x & <span class="number">1</span>);</span><br><span class="line"> x >>= <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> s;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">memset</span>(dp, <span class="number">0x3f</span>, <span class="built_in">sizeof</span>(dp));</span><br><span class="line"> <span class="built_in">memset</span>(dp[<span class="number">1</span>], <span class="number">0</span>, <span class="built_in">sizeof</span>(dp[<span class="number">1</span>]));</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n);</span><br><span class="line"> N = (<span class="number">1</span> << n) - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">1</span>, n)</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &a[i][j]);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">2</span>, n) { <span class="comment">// 收到的是第几个人 </span></span><br><span class="line"> <span class="built_in">rep</span>(f, <span class="number">1</span>, n) { <span class="comment">// 从谁那里传过来的 </span></span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">0</span>, N) { <span class="comment">// 上一个状态 </span></span><br><span class="line"> <span class="keyword">if</span>(!(j & (<span class="number">1</span> << f - <span class="number">1</span>)) || <span class="built_in">num</span>(j) != i - <span class="number">1</span>) <span class="comment">// 判断此状态是否和 i、k 贴合</span></span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> <span class="built_in">rep</span>(k, <span class="number">1</span>, n) { <span class="comment">// 谁收到了 </span></span><br><span class="line"> <span class="keyword">if</span>(!(j & (<span class="number">1</span> << k - <span class="number">1</span>)) && f != k)</span><br><span class="line"> dp[i][j | (<span class="number">1</span> << k - <span class="number">1</span>)][k] = <span class="built_in">min</span>(dp[i][j | (<span class="number">1</span> << k - <span class="number">1</span>)][k], dp[i - <span class="number">1</span>][j][f] + a[f][k]);</span><br><span class="line"> <span class="keyword">if</span>(i == n)</span><br><span class="line"> ans = <span class="built_in">min</span>(ans, dp[i][j | (<span class="number">1</span> << k - <span class="number">1</span>)][k]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d"</span>, ans);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h3 id="C-项链"><a href="#C-项链" class="headerlink" title="C. 项链"></a>C. 项链</h3><blockquote><p>题意:有 $n$ 个贝壳和 $m$ 组贝壳能连接的关系,每一组关系形如 $a_i,b_i$ 代表第 $a_i$ 和第 $b_i$ 个贝壳可以连接。项链是首尾相接的,而且要求用上所有的贝壳。求组成项链的方案数量。多组数据,$1\le T\le 5$,$1\le n\le 18$。</p></blockquote><p>这道题打 $\Theta(n^22^n)$ 会 T + M 到飞起,所以还是老老实实打 $\Theta(n2^n)$ 吧。</p><p>因为项链是环状,所以哪一个贝壳在第一个都无所谓。既然如此,我们不妨让第一个贝壳为首,只要最后一个贝壳可以和它相连就可以了。这样我们就把环搞成了链。</p><p>接着,$dp_{i,j}$ 表示目前的最后一个贝壳是第 $i$ 个,状态为 $j$(这次还是从低到高)时的方案总数量。状态转移时枚举上一个贝壳是哪一个,如果两个贝壳可以连接就加上。<del>都是套路。</del></p><script type="math/tex; mode=display">dp_{i,j}=\sum\limits_{k=1}^n dp_{k,j-2^i}</script><p>初始化 $dp_{0,0}=1$。</p><p>记得要开 <code>long long</code>。</p><p>Code:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> ll long long</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="number">1</span> << <span class="number">18</span>) + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m, u, v;</span><br><span class="line">ll dp[<span class="number">20</span>][maxn];</span><br><span class="line"><span class="type">bool</span> b[<span class="number">20</span>][<span class="number">20</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">while</span>(<span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &n, &m) != EOF) {</span><br><span class="line"> <span class="built_in">memset</span>(dp, <span class="number">0</span>, <span class="keyword">sizeof</span> dp);</span><br><span class="line"> <span class="built_in">memset</span>(b, <span class="number">0</span>, <span class="keyword">sizeof</span> b);</span><br><span class="line"> <span class="type">int</span> N = (<span class="number">1</span> << n) - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, m) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &u, &v);</span><br><span class="line"> --u, --v;</span><br><span class="line"> b[u][v] = b[v][u] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> dp[<span class="number">0</span>][<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, n - <span class="number">1</span>)</span><br><span class="line"> b[i][i] = <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">0</span>, N) {</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, n - <span class="number">1</span>) {</span><br><span class="line"> <span class="keyword">if</span>(!(j & (<span class="number">1</span> << i)))</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> <span class="built_in">rep</span>(k, <span class="number">0</span>, n - <span class="number">1</span>) {</span><br><span class="line"> <span class="keyword">if</span>(j & (<span class="number">1</span> << k) && b[i][k])</span><br><span class="line"> dp[i][j] += dp[k][j - (<span class="number">1</span> << i)];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> ll ans = <span class="number">0</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, n - <span class="number">1</span>) {</span><br><span class="line"> <span class="keyword">if</span>(b[i][<span class="number">0</span>])</span><br><span class="line"> ans += dp[i][N];</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%lld\n"</span>, ans);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>PS. 话说,你们有没有发现其实状压从 $0$ 开始貌似更好操作一些,因为二进制的最低为代表的是 $2^0$ 而不是 $2^1$ 嘛。比如这道题,我之前是从 $1$ 开始的死活过不了,结果改成从 $0$ 开始就神奇地过了 <del>(XSC062:说啥呢,还不是老子给你改的)</del>,只可惜我从 $1$ 开始写习惯了,所以一般来说只要能过我都还是从 $1$ 开始……</p><hr><h3 id="D-国王"><a href="#D-国王" class="headerlink" title="D. 国王"></a>D. 国王</h3><p><del>其实就是互不侵犯,鬼知道为啥要改名。</del></p><blockquote><p>题意:在 $n\times n$ 的棋盘上放 $k$ 个国王,国王可攻击相邻的 $8$ 个格子,求使它们无法互相攻击的方案总数。</p></blockquote><p>这道题因为规定了个数为 $k$ 个,所以除了状压需要的第 $i$ 行和状态为 $j$ 之外(这次 $j$ 从高到低和从低到高没有影响,可以自己想一想为什么 qwq),还需要一维确定目前已经有的个数。</p><p>$dp_{i,j,k}$ 代表前 $i$ 行,第 $i$ 行状态为 $j$,已经放了 $k$ 个国王时的方案总数量。</p><p>判断是否相邻方法和 A 题类似,都是用位运算。这道题多了四个角落的格子,其实很好解决,只需要把上一行左移一位按位与,右移一位按位与,看结果是不是 $0$ 即可(原理也在 A 当中说了)。</p><p>状态转移:</p><script type="math/tex; mode=display">dp_{i,j,k}=\sum\limits_{l=0}^{2^n-1}dp_{i-1,l,k-\text{numone}(l)}</script><p>($\text{numone}$ 指一个二进制数中 $1$ 的个数,所以 $numone$ 可以预处理或者是打一个函数。)</p><p>Code:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cctype></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> ll long long</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> IO {</span><br><span class="line"> <span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">read</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="type">int</span> x = <span class="number">0</span>, w = <span class="number">0</span>;</span><br><span class="line"> <span class="type">char</span> ch = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span>(!<span class="built_in">isdigit</span>(ch)) {</span><br><span class="line"> w |= ch == <span class="string">'-'</span>;</span><br><span class="line"> ch = <span class="built_in">getchar</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">while</span>(<span class="built_in">isdigit</span>(ch)) {</span><br><span class="line"> x = (x << <span class="number">3</span>) + (x << <span class="number">1</span>) + (ch ^ <span class="number">48</span>);</span><br><span class="line"> ch = <span class="built_in">getchar</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> w ? -x : x;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">write</span><span class="params">(ll x)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(x < <span class="number">0</span>) <span class="built_in">putchar</span>(<span class="string">'-'</span>), x = -x;</span><br><span class="line"> <span class="keyword">if</span>(x > <span class="number">9</span>) <span class="built_in">write</span>(x / <span class="number">10</span>);</span><br><span class="line"> <span class="built_in">putchar</span>(x % <span class="number">10</span> + <span class="string">'0'</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> IO;</span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = <span class="number">1050</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, k;</span><br><span class="line">ll ans, dp[<span class="number">15</span>][<span class="number">105</span>][maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">num</span><span class="params">(<span class="type">int</span> x)</span> </span>{</span><br><span class="line"> <span class="type">int</span> s = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span>(x) {</span><br><span class="line"> s += x & <span class="number">1</span>; <span class="comment">// 末位是不是 1</span></span><br><span class="line"> x >>= <span class="number">1</span>; <span class="comment">// 右移一位,把判断过的末位扔掉</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> s;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> n = <span class="built_in">read</span>(), k = <span class="built_in">read</span>();</span><br><span class="line"> <span class="keyword">if</span>(k > (n * n) >> <span class="number">1</span>) {</span><br><span class="line"> <span class="built_in">putchar</span>(<span class="string">'0'</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="type">int</span> N = (<span class="number">1</span> << n) - <span class="number">1</span>;</span><br><span class="line"> dp[<span class="number">0</span>][<span class="number">0</span>][<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">0</span>, k) {</span><br><span class="line"> <span class="built_in">rep</span>(x, <span class="number">0</span>, N) {</span><br><span class="line"> <span class="keyword">if</span>(x & (x << <span class="number">1</span>) || j < <span class="built_in">num</span>(x))</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> <span class="built_in">rep</span>(y, <span class="number">0</span>, N) { <span class="comment">// 枚举上一行的状态</span></span><br><span class="line"> <span class="keyword">if</span>(j >= <span class="built_in">num</span>(y) && !(x & y) && !(y & (y << <span class="number">1</span>)) && !(x & (y << <span class="number">1</span>)) && !(x & (y >> <span class="number">1</span>))) <span class="comment">// 判断条件</span></span><br><span class="line"> dp[i][j][y] += dp[i - <span class="number">1</span>][j - <span class="built_in">num</span>(y)][x];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, N)</span><br><span class="line"> ans += dp[n][k][i]; <span class="comment">// 统计答案</span></span><br><span class="line"> <span class="built_in">write</span>(ans);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>PS. 有一个点需要大家注意,就是打状压的时候一定要弄清楚每一层循环的变量代表的是啥,状态转移的时候需要注意,尤其是同一种类型的变量!不然打错了很难调出来。</p><hr><h3 id="E-Hie-with-the-Pie"><a href="#E-Hie-with-the-Pie" class="headerlink" title="E. Hie with the Pie"></a>E. Hie with the Pie</h3><blockquote><p>题意:一个有 $n+1$ 个点的有向完全图,结点依次编号为 $0,1,\ldots,n$,给出其邻接矩阵(注意从 $i$ 到 $j$ 的距离不一定等于从 $j$ 到 $i$ 的距离)。请求出从 $0$ 号点出发,走过 $1$ 到 $n$ 号点至少一次,然后再回到 $0$ 号点的最短路。$1\le n\le 10$。</p></blockquote><p>注意到每个点都必须走,于是想到状压。</p><p>$dp_{i,j}$ 表示从 $0$ 出发,到了 $i$ 点,且状态为 $j$ 时的最短路。状态转移时,枚举上一个经过的点为 $k$,此时我们发现状态转移需要知道任意两个点 ($i$ 和 $k$)之间的最短路,所以我们先跑一遍 Floyd 预处理出任意两个点之间的最短路再转移,方程如下:</p><script type="math/tex; mode=display">dp_{i,j}=\min\limits_{k=1}^n\{dp_{k,j-2^{i-1}}+f(i,k)\}</script><p>然鹅,这道题难在于细节。</p><p>首先注意循环几层的顺序,外层必须是 $j$,因为 $j$ 的转移是从小到大的转移,而 $i$ 和 $k$ 都是无序的,为了保证 dp 的无后效性必须先枚举 $j$。</p><p><del>某搜索大佬:关我什么事。</del></p><p>其次注意答案的求法,我们不能直接枚举 $\min\{dp_{i,2^n-1}\}$,因为题目要求我们必须返回 $0$ 点,所以还得加上一个 $i$ 返回 $0$ 的最短路,即求 $\min\{dp_{i,2^n-1}+f(0,i)\}$。</p><p>Code:(长得和题解有点不一样,凑合着看吧 qwq)</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="number">1</span> << <span class="number">11</span>) + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, G[<span class="number">15</span>][<span class="number">15</span>], dp[<span class="number">15</span>][maxn], f[<span class="number">15</span>][<span class="number">15</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">min</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <span class="keyword">return</span> x < y ? x : y; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">Floyd</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">1</span>, n)</span><br><span class="line"> f[i][j] = G[i][j];</span><br><span class="line"> <span class="built_in">rep</span>(k, <span class="number">1</span>, n)</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">1</span>, n)</span><br><span class="line"> f[i][j] = <span class="built_in">min</span>(f[i][j], f[i][k] + f[k][j]);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">while</span>(<span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n) != EOF) {</span><br><span class="line"> <span class="built_in">memset</span>(dp, <span class="number">0x3f</span>, <span class="built_in">sizeof</span>(dp));</span><br><span class="line"> ++n;</span><br><span class="line"> <span class="type">int</span> N = (<span class="number">1</span> << n) - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">1</span>, n)</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &G[i][j]);</span><br><span class="line"> dp[<span class="number">1</span>][<span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line"> <span class="built_in">Floyd</span>();</span><br><span class="line"> <span class="built_in">rep</span>(k, <span class="number">0</span>, N) {</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> <span class="keyword">if</span>(!(k & (<span class="number">1</span> << i - <span class="number">1</span>)))</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">1</span>, n) {</span><br><span class="line"> <span class="keyword">if</span>(i == j || !(k & (<span class="number">1</span> << j - <span class="number">1</span>)))</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> dp[i][k] = <span class="built_in">min</span>(dp[i][k], dp[j][k ^ (<span class="number">1</span> << i - <span class="number">1</span>)] + f[j][i]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="type">int</span> ans = <span class="number">1</span> << <span class="number">30</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> ans = <span class="built_in">min</span>(ans, dp[i][N] + f[i][<span class="number">1</span>]);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d\n"</span>, ans);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h3 id="F-Traveling"><a href="#F-Traveling" class="headerlink" title="F. Traveling"></a>F. Traveling</h3><blockquote><p>题意:一个人要去 $N$ 个城市旅游,他可以从任意城市开始,城市之间有 $m$ 个道路,每个道路所花费的费用不用,求解出遍历所有城市,且每个城市去过的次数不超过两次的最小花费。$1\le N\le 10$。</p></blockquote><p>肉眼可见这题是个三进制的问题。不同于二进制,三进制没有系统内置的位运算,我们该怎么处理呢?</p><p>我们可以开两个数组进行预处理:$mi3$ 和 $num3$。$mi3_i$ 的值为 $3^i$,$num3_{i,j}$ 代表 $i$ 这个数的三进制的第 $j$ 位是 $0,1$ 还是 $2$。为了方便思考,$num3_i$ 按照高位到低位从左到右排。 比如一个数 $15$,三进制为 $121$,那么 $num3_{15}$ 如下:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">num3[15]:</span><br><span class="line">下标: 0 1 2 3 4 5 6 7 8 9 10</span><br><span class="line">权值: 0 0 0 0 0 0 0 0 1 2 1</span><br></pre></td></tr></table></figure><p>因为 $N\le 10$,所以这个数最多也就到 $3^{10}-1$,再多开一位,下标范围就是 $0\sim 10$。</p><p>至于使用方法嘛……往下看!</p><p>预处理工作做完后,输入图。为了方便,我们还是以 $0\sim n-1$ 编号城市。</p><p>接下来就是 dp:</p><p>$dp_{i,j}$ 代表到了第 $i$ 个城市之后状态为 $j$ 的最小代价,这里 $j$ 从低位到高位表示的城市编号依次递增。</p><p>接着再套一层循环,枚举上一步是从 $k$ 城市到 $i$ 城市,计算就可以了。emm,注意还是要先跑一遍 Floyd。</p><script type="math/tex; mode=display">dp_{i,j}=\min\limits_{k=0}^{n-1}\{dp_{k,j-3^i+f(i,k)}\}</script><p>状态转移方程很简单,相信大家都会,但是有几个细节我错了很久:</p><ol><li>状态转移时几层循环的顺序。注意到状态转移的时候,只有 $j$ 是一直在增加的,$i$ 和 $k$ 都是乱的。所以第一层循环应该是 $j$,其次是 $i$,最后是 $k$。</li><li>因为此处 $j$ 是按照从低位到高位从右到左的顺序排,但是预处理是从高位到低位从左到右,所以可以注意到状态转移时可以直接使用 $3^i$,但是在判断的时候需要特别注意是 $3^{i/k}$ 还是 $3^{10-i/k}$。</li></ol><p>我在调这道题的时候 mjl 叫我写注释,所以我写了一个比较详细的注释,大家可以参考。</p><p><del>感谢 XSC062 救了我一命!不过这个代码我不知道是有 UB 还是什么,使用 <code>C++17(Clang)</code> 可以 AC,而使用 <code>C++14(GCC8)</code> 会 WA $\text{5pts}$,如果有大佬愿意帮我看一下是怎么回事,那也是极好的。</del></p><p>Code:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> ll long long</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = <span class="number">15</span>;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N3 = <span class="number">6e4</span> + <span class="number">5</span>; <span class="comment">// 3 ^ 10</span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m, f[maxn][maxn], dp[maxn][N3];</span><br><span class="line"><span class="type">int</span> mi3[maxn], num3[N3][maxn];</span><br><span class="line"><span class="type">bool</span> b[N3];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">min</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <span class="keyword">return</span> x < y ? x : y; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> mi3[<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, <span class="number">10</span>)</span><br><span class="line"> mi3[i] = mi3[i - <span class="number">1</span>] * <span class="number">3</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, N3) {</span><br><span class="line"> <span class="type">int</span> x = i, s = <span class="number">10</span>;</span><br><span class="line"> <span class="keyword">while</span>(x) {</span><br><span class="line"> num3[i][s] = x % <span class="number">3</span>;</span><br><span class="line"> x /= <span class="number">3</span>;</span><br><span class="line"> --s;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">while</span>(~<span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &n, &m)) {</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, N3)</span><br><span class="line"> b[i] = <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, N3) {</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">10</span> - n + <span class="number">1</span>, <span class="number">10</span>)</span><br><span class="line"> b[i] &= num3[i][j] > <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">memset</span>(f, <span class="number">0x3f</span>, <span class="built_in">sizeof</span>(f));</span><br><span class="line"> <span class="built_in">memset</span>(dp, <span class="number">0x3f</span>, <span class="built_in">sizeof</span>(dp));</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, n - <span class="number">1</span>)</span><br><span class="line"> dp[i][mi3[i]] = <span class="number">0</span>;</span><br><span class="line"> <span class="type">int</span> u, v, w;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, m) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d %d"</span>, &u, &v, &w);</span><br><span class="line"> --u, --v;</span><br><span class="line"> f[u][v] = f[v][u] = <span class="built_in">min</span>(f[u][v], w);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">0</span>, mi3[n] - <span class="number">1</span>) { <span class="comment">// j 表示到了 i 之后的状态,三进制表示下最低位代表 0 城市(3^0),倒数第二位表示 1 城市(3^1),i 城市即为 3^i </span></span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, n - <span class="number">1</span>) { <span class="comment">// 目前到了第 i 个城市</span></span><br><span class="line"> <span class="keyword">if</span>(!num3[j][<span class="number">10</span> - i]) <span class="comment">// 如果 j 表示 i 去过的位数为 0 则说明没去过 i,不合法</span></span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> <span class="comment">// 这里是 10 - i 是因为 num3 数组是从左到右编号递增,但是 j 是从右往左依次递增,所以要转换一下 </span></span><br><span class="line"> <span class="built_in">rep</span>(k, <span class="number">0</span>, n - <span class="number">1</span>) <span class="comment">// 从 k 城市到的 i 城市</span></span><br><span class="line"> <span class="keyword">if</span>(num3[j][<span class="number">10</span> - k] > <span class="number">0</span>) <span class="comment">// j 当中也必须经过至少一次 k 才合法,10 - k 同理 </span></span><br><span class="line"> dp[i][j] = <span class="built_in">min</span>(dp[i][j], dp[k][j - mi3[i]] + f[i][k]); <span class="comment">// 状态转移,之前的状态少去了一次 i 所以要减 3^i </span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="type">int</span> ans = <span class="number">1</span> << <span class="number">30</span>;</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">0</span>, n - <span class="number">1</span>)</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, mi3[n] - <span class="number">1</span>)</span><br><span class="line"> <span class="keyword">if</span>(b[i])</span><br><span class="line"> ans = <span class="built_in">min</span>(ans, dp[j][i]); <span class="comment">// 如果所有城市都去过就统计答案 </span></span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d\n"</span>, ans == <span class="number">0x3f3f3f3f</span> ? <span class="number">-1</span> : ans);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h3 id="H-炮兵阵地"><a href="#H-炮兵阵地" class="headerlink" title="H. 炮兵阵地"></a>H. 炮兵阵地</h3><blockquote><p>题意:有 $N\times M$ 的地区,每一个可能是山地(<code>H</code>)或者平原(<code>P</code>),只有平原才能有炮兵。每个炮兵的攻击范围是上下左右两个格子。给出地形图,求炮兵不相互攻击时最多能部署的炮兵数量。$1\le N\le 100,1\le M \le 10$。</p></blockquote><p><del>别问我 G 去哪了,问就是还没做出来。</del></p><p>这题就是一个 A 和 D 的缝合怪,确定一个攻击范围,然后山地上不能有炮兵就像 A 的有些格子不能种草一样。因为上下左右是两格,所以状态转移的时候不仅要枚举上一行的状态,还要枚举上上一行的状态,这么搞不 <code>TLE&MLE</code> 才怪呢。</p><p>怎么解决呢,其实有一个办法,就是我们先把所有满足条件的一行的排列 dfs 出来,<del>通过实验</del>我们发现最多也就只有 $60$ 种符合要求的排列,所以枚举状态的时候每一层最多就 $60$,就不会时间内存双爆炸啦。</p><p>注意一下这里是求最多能放多少个炮兵,所以两层状态的答案是要加起来取 $\max$ 而非乘起来。<del>今天也是把加法原理和乘法原理弄混的一天呢。</del></p><p>其他就没什么好说的了。</p><p>Code:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> ll long long</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">char</span> a[<span class="number">105</span>][<span class="number">105</span>];</span><br><span class="line"><span class="type">int</span> n, m, N, tot, num[<span class="number">105</span>], qn[<span class="number">65</span>], sum[<span class="number">65</span>], dp[<span class="number">105</span>][<span class="number">65</span>][<span class="number">65</span>];</span><br><span class="line"><span class="type">bool</span> b[<span class="number">105</span>], q[<span class="number">65</span>][<span class="number">105</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">max</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <span class="keyword">return</span> x > y ? x : y; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> t, <span class="type">int</span> ls)</span> </span>{ <span class="comment">// 求满足条件的所有一行的情况,两个炮兵之间至少相隔两个格子,不考虑山地和平原</span></span><br><span class="line"> <span class="keyword">if</span>(t == m + <span class="number">1</span>) {</span><br><span class="line"> ++tot;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, m)</span><br><span class="line"> q[tot][i] = b[i];</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(ls > <span class="number">2</span>) {</span><br><span class="line"> b[t] = <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">dfs</span>(t + <span class="number">1</span>, <span class="number">1</span>);</span><br><span class="line"> b[t] = <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">dfs</span>(t + <span class="number">1</span>, ls + <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">getnum</span><span class="params">(<span class="type">int</span> x)</span> </span>{</span><br><span class="line"> <span class="type">int</span> s = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span>(x) {</span><br><span class="line"> s += x & <span class="number">1</span>;</span><br><span class="line"> x >>= <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> s;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &n, &m);</span><br><span class="line"> N = (<span class="number">1</span> << m) - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">dfs</span>(<span class="number">1</span>, <span class="number">3</span>);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, tot)</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">1</span>, m)</span><br><span class="line"> qn[i] = (qn[i] << <span class="number">1</span>) + q[i][j];</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, tot)</span><br><span class="line"> sum[i] = <span class="built_in">getnum</span>(qn[i]);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"\n"</span>);</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">1</span>, m)</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%c"</span>, &a[i][j]);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">1</span>, m)</span><br><span class="line"> num[i] = (num[i] << <span class="number">1</span>) + (a[i][j] == <span class="string">'H'</span> ? <span class="number">0</span> : <span class="number">1</span>);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">1</span>, tot) {</span><br><span class="line"> <span class="keyword">if</span>((qn[j] | num[i]) ^ num[i]) <span class="comment">// 山地上不能有炮兵,此处判断和 A 题相似</span></span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> <span class="built_in">rep</span>(k, <span class="number">1</span>, tot) {</span><br><span class="line"> <span class="keyword">if</span>(qn[k] & qn[j])</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> <span class="built_in">rep</span>(l, <span class="number">1</span>, tot)</span><br><span class="line"> <span class="keyword">if</span>(!(qn[l] & qn[j]))</span><br><span class="line"> dp[i][j][k] = <span class="built_in">max</span>(dp[i][j][k], dp[i - <span class="number">1</span>][k][l] + sum[j]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="type">int</span> ans = <span class="number">0</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, tot)</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">1</span>, tot)</span><br><span class="line"> ans = <span class="built_in">max</span>(ans, dp[n][i][j]);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d"</span>, ans);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h3 id="O-集合选数"><a href="#O-集合选数" class="headerlink" title="O. 集合选数"></a>O. 集合选数</h3><blockquote><p>题意:有一种集合,若 $x$ 在集合中,则 $2x$ 和 $3x$ 都不能在集合中。对于任意一个正整数 $n$,求出 ${1, 2,\ldots, n}$ 这个集合的满足上述约束条件的子集的个数,结果对 $10^9+1$ 取模。$1\le n\le 10^5$。</p></blockquote><p><del>这思路,老师不讲真的可以想到吗!</del></p><p>这题乍一看没什么头绪,咱要不先列个表:</p><script type="math/tex; mode=display">\begin{matrix}1 & 2 & 4 & 8 &\cdots\\ 3 & 6 & 12 & 24 &\cdots\\9 & 18 & 36 & 72 &\cdots \\\cdots\end{matrix}</script><p>观察一下,思考一下:当选 $1$ 的时候,$2,3$ 不能选;选 $2$ 的时候,$1,4,6$ 不能选;选 $6$ 的时候,$2,3,12,18$ 不能选……</p><p>有没有发现什么?</p><p>这不就是在这个矩阵中不能取相邻的数吗!</p><p>那我们就构造一个这样的矩阵,左上角数字为 $1$,最上面一行为 $2$ 的幂次,最左边一行为 $3$ 的幂次,剩下的数就由那一个位置上对应的 $2$ 的幂次和 $3$ 的幂次相乘,然后按照 A 题的求法求是不是就可以了?</p><p>想到这一层,我们就已经成功了一半。接下来的一半,还得看几个细节:</p><p>一、有些数,比如 $5$,貌似不在这个矩阵里面。</p><p>这个东西解决办法也不难,如果找到有数字不在之前列到过的矩阵里面,我们只需要以这个数为左上角,然后再构造矩阵:</p><script type="math/tex; mode=display">\begin{matrix}5(1\times 5) & 10(2\times 5) & 20(4\times 5) & 40(8\times 5) &\cdots\\ 15(3\times 5) & 30(6\times 5) & 60(12\times 5) & 120(24\times 5) &\cdots\\45(9\times 5) & 90(18\times 5) & 180(36\times 5) & 360(72\times 5) &\cdots \\\cdots\end{matrix}</script><p>没错,我们只需要在刚才那个矩阵的基础上,把每个数都乘以左上角那个数,就可以了!</p><p>用一个 <code>bool</code> 数组存一下每个数字是否已经存在,在构造矩阵的过程中,遇到一个数就把它标记为已经出现过。求解答案时依次枚举 $1\sim n$,如果发现有数没有枚举到,就以这个数为左上角构造矩阵再求解。</p><p>由于各个矩阵之间没有什么关系,所以方案的选择是任意的,即每个矩阵得出的答案相乘。</p><p>另外,需要注意一下,如果你和我一样是按照先构造第一行和第一列,再相乘构造整个矩阵的话,记得两数相乘时需要除以左上角那个数,因为相乘的时候两边系数都算了一次,需要去重。</p><p>二、矩阵的大小?</p><p>构造第一行和第一列的时候,肯定是到 $n$ 就结束了。但是相乘的时候,仍然会有数大小超过 $n$,那么这些超过 $n$ 就不能选,类似于 A 里面有些格子里不能种草,这个用一个 <code>bool</code> 数组标记即可。</p><p>因为 $n$ 最多为 $10^5$,$\log_2(10^5)\approx 17,\log_3\approx 12$,所以矩阵的大小不会超过 $17\times 12$,数组没有必要开太大。</p><p>另外,因为 $dp$ 数组等大小比较大,大家一定要注意不能用 <code>memset</code>,直接需要清空多少就清空多少,不然会 T 飞。<del>当然,如果您是 $90$ 分的话,打表也是一个不错的选择。</del></p><p>Code:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> ll long long</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="number">1</span> << <span class="number">17</span>) + <span class="number">5</span>;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">100000</span>;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> mod = <span class="number">1000000001</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, x2[<span class="number">20</span>], x3[<span class="number">20</span>], _x2, _x3, __x2, __x3, num[<span class="number">20</span>], dp[<span class="number">20</span>][maxn];</span><br><span class="line">ll a[<span class="number">20</span>][<span class="number">20</span>];</span><br><span class="line"><span class="type">bool</span> b[<span class="number">20</span>][<span class="number">20</span>], gz[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">Make</span><span class="params">(<span class="type">int</span> o)</span> </span>{ <span class="comment">// 构造矩阵,一个横杠是矩阵的长宽,两个横杠是权值</span></span><br><span class="line"> _x2 = <span class="number">0</span>, _x3 = <span class="number">0</span>, __x2 = o, __x3 = o;</span><br><span class="line"> <span class="keyword">while</span>(__x2 <= n)</span><br><span class="line"> x2[++_x2] = __x2, __x2 <<= <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span>(__x3 <= n)</span><br><span class="line"> x3[++_x3] = __x3, __x3 = (__x3 << <span class="number">1</span>) + __x3;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, _x2)</span><br><span class="line"> a[<span class="number">1</span>][i] = x2[i], gz[x2[i]] = <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, _x3)</span><br><span class="line"> a[i][<span class="number">1</span>] = x3[i], gz[x3[i]] = <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">2</span>, _x3)</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">2</span>, _x2)</span><br><span class="line"> a[i][j] = a[<span class="number">1</span>][j] * a[i][<span class="number">1</span>] / o;</span><br><span class="line"> </span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, _x3)</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">1</span>, _x2) {</span><br><span class="line"> b[i][j] = (a[i][j] <= n);</span><br><span class="line"> <span class="keyword">if</span>(b[i][j])</span><br><span class="line"> gz[a[i][j]] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">Solve</span><span class="params">()</span> </span>{</span><br><span class="line"><span class="comment">// memset(dp, 0, sizeof(dp));</span></span><br><span class="line"><span class="comment">// memset(num, 0, sizeof(num));</span></span><br><span class="line"> <span class="type">int</span> ans = <span class="number">0</span>, q = (<span class="number">1</span> << _x2) - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, _x3)</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">0</span>, q)</span><br><span class="line"> dp[i][j] = <span class="number">0</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, _x3)</span><br><span class="line"> num[i] = <span class="number">0</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, _x3)</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">1</span>, _x2)</span><br><span class="line"> num[i] = (num[i] << <span class="number">1</span>) + b[i][j];</span><br><span class="line"> dp[<span class="number">0</span>][<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, _x3) {</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">0</span>, q) {</span><br><span class="line"> <span class="keyword">if</span>(j & (j << <span class="number">1</span>) || (j | num[i]) ^ num[i])</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> <span class="built_in">rep</span>(k, <span class="number">0</span>, q) {</span><br><span class="line"> <span class="keyword">if</span>(!(k & j))</span><br><span class="line"> dp[i][j] = (dp[i][j] + dp[i - <span class="number">1</span>][k]) % mod;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, q)</span><br><span class="line"> ans = (ans + dp[_x3][i]) % mod;</span><br><span class="line"> <span class="keyword">return</span> ans;</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n);</span><br><span class="line"> <span class="keyword">if</span>(n == <span class="number">100000</span>) {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"964986022"</span>); <span class="comment">// 打表出奇迹</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> ll s = <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> <span class="keyword">if</span>(gz[i])</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> <span class="built_in">Make</span>(i);</span><br><span class="line"> s = (s * <span class="built_in">Solve</span>()) % mod;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%lld"</span>, s);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">都是套路,但是细节巨多。</summary>
<category term="学习笔记" scheme="https://blog.liynw.top/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<category term="动态规划" scheme="https://blog.liynw.top/tags/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/"/>
</entry>
<entry>
<title>CF899E Segments Removal 题解</title>
<link href="https://blog.liynw.top/posts/615100e6/"/>
<id>https://blog.liynw.top/posts/615100e6/</id>
<published>2022-01-26T22:59:55.000Z</published>
<updated>2022-02-20T11:45:35.000Z</updated>
<content type="html"><![CDATA[<p>这是我们考试题,我做了 $75$ 分,最后才发现是元素入队的时候没有赋值……</p><hr><h3 id="Problem"><a href="#Problem" class="headerlink" title="Problem"></a>Problem</h3><blockquote><p>有一个长度为 $n$ 的整数数组,对数组执行若干次操作。每一次找到连续相等整数的最长段(如果有多个段长度相同,选择最靠左边的段)并删除它。要求计算经过多少次操作后数组为空。</p></blockquote><hr><h3 id="Solution"><a href="#Solution" class="headerlink" title="Solution"></a>Solution</h3><p>因为前两天才调完<a href="https://www.luogu.com.cn/problem/P7912">小熊的果篮</a>,记忆犹新,所以立刻想到了<strong>队列+链表</strong>的做法。然后再读题,发现需要找长度最长的区间,不能用普通队列,要用<strong>优先队列</strong>。</p><p>我们先把所有的区间都找出来,存储每一个区间的左端点,长度(这样就可以算出右端点了)和这个区间数字的值。然后把这些区间全部按照顺序弄到一个双向链表里面,并把需要的值加入优先队列。</p><p>详细的讲解在代码注释里。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 定义结构体,需要存区间左端点,区间长度和它在链表里的下标</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">node</span> { <span class="type">int</span> l, len, id; };</span><br><span class="line">std::priority_queue<node> q;</span><br><span class="line"><span class="comment">// 定义排序规则:区间长度,一样时左边优先</span></span><br><span class="line"><span class="type">bool</span> <span class="keyword">operator</span><(node x, node y) { <span class="keyword">return</span> (x.len != y.len) ? (x.len < y.len) : (x.id > y.id); }</span><br><span class="line"></span><br><span class="line"><span class="comment">// lst 为上一个区间的左端点,因为我们要计算区间长度,所以需要用这个区间和上个区间的左端点算上一个区间的长度,需要存一下</span></span><br><span class="line"><span class="type">int</span> ans = <span class="number">0</span>, lst = <span class="number">0</span>; </span><br><span class="line">a[<span class="number">0</span>] = a[n + <span class="number">1</span>] = <span class="number">-1</span>; <span class="comment">// 特殊处理头尾端点,以免错误合并</span></span><br><span class="line"><span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> <span class="keyword">if</span>(a[i] != a[i - <span class="number">1</span>]) { <span class="comment">// 说明这个数是一个区间的开头</span></span><br><span class="line"> num[++k] = a[i];</span><br><span class="line"> l[k] = k - <span class="number">1</span>; <span class="comment">// 初始化链表</span></span><br><span class="line"> r[k] = k + <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span>(k != <span class="number">1</span>) { <span class="comment">// 如果这个区间有上一个,即不是第一个</span></span><br><span class="line"> q.<span class="built_in">push</span>(<span class="built_in">node</span>({lst, i - lst, k - <span class="number">1</span>})); <span class="comment">// 元素入队</span></span><br><span class="line"> L[k - <span class="number">1</span>] = lst, LEN[k - <span class="number">1</span>] = i - lst; <span class="comment">// 记录区间左端点和长度</span></span><br><span class="line"> }</span><br><span class="line"> lst = i; <span class="comment">// 更新上一个区间的左端点</span></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">q.<span class="built_in">push</span>(<span class="built_in">node</span>({lst, n - lst + <span class="number">1</span>, k})); <span class="comment">// 最后一个区间也需要处理</span></span><br><span class="line">L[k] = lst, LEN[k] = n - lst + <span class="number">1</span>;</span><br><span class="line">r[<span class="number">0</span>] = <span class="number">1</span>, l[k + <span class="number">1</span>] = k; <span class="comment">// 链表的初始化</span></span><br></pre></td></tr></table></figure><p>接着就是核心代码了。</p><p>我们用一个 <code>bool</code> 数组标记一个区间是否被取过,然后从队列里面不停取元素。</p><ul><li>若此区间已经被标记过了就直接跳过。</li><li>若此区间没有被取过,就标记一下这个区间,此时又取了一个区间,答案需要 $+1$,然后检查一下它的左右两个区间是否需要被合并;如果需要,就把两个区间合并到它左边那个区间,并标记它右边那个区间。</li></ul><p>这句话信息量有点大,是什么意思呢?</p><p>说明我们拿到一个没被取过的区间时,需要做这几件事:</p><ol><li>把这个区间标记为“已经被取过”。</li><li>因为又取了一个区间,所以答案要 $+1$。</li><li>把这个区间从链表里删掉。</li><li>检查这个被删除的区间的左边的区间(命名为 $l$)和它右边的区间(命名为 $r$)是否需要被合并,也就是说这两个区间的值是不是一样的,如果是一样的,那这个区间被取了之后,$l$ 和 $r$ 就变成了一个区间,所以需要被合并。</li><li>合并两个区间的时候,可以把 $l$ 的长度改为两个区间的长度相加,然后把 $r$ 删掉。需要注意 $r$ 也要被标记。</li><li>把更新的 $l$ 加入队列。</li></ol><p>这个时候就会有小朋友问了:此时队列里还有原来的 $l$,是不是需要删掉?</p><p>答案是不需要。因为优先队列的排序规则是按照长度从大到小排的,所以更新后的 $l$ 一定会比原来的 $l$ 先取出,取出之后我们就标记了 $l$,也就不会重复取到了。</p><p>给一下代码。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">remove</span><span class="params">(<span class="type">int</span> x)</span> </span>{</span><br><span class="line"> id_use[x] = <span class="number">1</span>; <span class="comment">// 实现时可以把标记的代码放在删除的函数里面</span></span><br><span class="line"> r[l[x]] = r[x];</span><br><span class="line"> l[r[x]] = l[x];</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span>(!q.<span class="built_in">empty</span>()) {</span><br><span class="line"> <span class="keyword">while</span>(!q.<span class="built_in">empty</span>() && id_use[q.<span class="built_in">top</span>().id]) <span class="comment">// 过滤掉已经被标记过的点</span></span><br><span class="line"> q.<span class="built_in">pop</span>();</span><br><span class="line"> <span class="keyword">if</span>(q.<span class="built_in">empty</span>()) <span class="comment">// 如果队列被取空了就直接跳过</span></span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> node u = q.<span class="built_in">top</span>();</span><br><span class="line"> q.<span class="built_in">pop</span>();</span><br><span class="line"> ++ans; <span class="comment">// 更新答案</span></span><br><span class="line"> <span class="keyword">if</span>(num[r[u.id]] == num[l[u.id]]) { <span class="comment">// 如果 l 和 r 需要被合并</span></span><br><span class="line"> LEN[l[u.id]] += LEN[r[u.id]]; <span class="comment">// 赋值,注意这里不写只能得 75 分</span></span><br><span class="line"> q.<span class="built_in">push</span>(<span class="built_in">node</span>({L[l[u.id]], LEN[l[u.id]], l[u.id]})); <span class="comment">// l 入队</span></span><br><span class="line"> <span class="built_in">remove</span>(r[u.id]); <span class="comment">// 删除 r</span></span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">remove</span>(u.id); <span class="comment">// 把这个区间删除</span></span><br><span class="line">}</span><br><span class="line"><span class="built_in">write</span>(ans - <span class="number">1</span>); <span class="comment">// 这里 -1 是因为头和尾会被错误合并,所以会多一次</span></span><br></pre></td></tr></table></figure><p>大概就是这样了吧。因为核心代码已经给出,所以不再给完整代码了。</p><p><del>另外就是祝贺一下 ljt 考试的时候终于没有写挂快读快写了。</del></p>]]></content>
<summary type="html">考试少写了一句话,25 分直接就没了 qwq</summary>
<category term="题解" scheme="https://blog.liynw.top/categories/%E9%A2%98%E8%A7%A3/"/>
<category term="链表" scheme="https://blog.liynw.top/tags/%E9%93%BE%E8%A1%A8/"/>
</entry>
<entry>
<title>2021.12.24 考试总结</title>
<link href="https://blog.liynw.top/posts/894fc8e0/"/>
<id>https://blog.liynw.top/posts/894fc8e0/</id>
<published>2022-01-26T22:58:31.000Z</published>
<updated>2022-02-01T10:10:08.000Z</updated>
<content type="html"><![CDATA[<h3 id="T1"><a href="#T1" class="headerlink" title="T1"></a>T1</h3><p>正解是单调队列,时间复杂度 $\Theta(n)$。</p><p>我们先把数组复制 $3$ 遍。等等,为什么不是两遍呢?</p><p>因为最大值有变化,某首歌是否满足条件的数据在变化,所以可能出现第一次可以播放,但第二次不行的情况。平时我们是复制两遍,所以这里要多复制一遍。</p><p>然后从第一首歌开始,一次遍历被复制了三遍的数组,维护一个单调递减的队列。当然,里面存的是数组下标,下标当然不是单调递减的,但是代表的喜爱值是递减的。</p><p>我们以样例举例:</p><p><code>3 2 5 3</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">i = 1 2 3 4 5 6 7 8 9 10 11 12</span><br><span class="line">a = 3 2 5 3 3 2 5 3 3 2 5 3</span><br><span class="line">ans = 0 0 0 0 0 0 0 0 0 0 0 0</span><br></pre></td></tr></table></figure><p>每次遍历到一个数,依次进行如下操作:</p><p>第一步:判断队首元素是否符合标准,当前遍历到的元素 $i$ 是否满足要求,即是否有 $a<em>i<\dfrac{a</em>{q.\text{front()}}}{2}$。如果是,那么计算队首元素的答案(从它开始最多可以放多少首歌,<strong>即为当前遍历到的歌曲编号减去队首元素的编号</strong>)并把队首元素弹出。</p><p><strong>注意队首可能不止一个元素不满足要求,需要连续弹出。</strong></p><p>比如我们遍历到了 $6$ 号,然后单调队列现在长这样:</p><p><code>front {3, 4, 5} back</code> 也就是 <code>front {5, 3, 3} back</code></p><p>本来没什么问题,但是注意到 $2<\frac{5}{2}$,所以如果播放了 $3$ 号歌曲,就不能播放 $6$ 号歌曲了。那么,从 $3$ 号歌曲开始播放最多能播放 $6-3=3$ 首歌,也就是 $3,4,5$ 这三首。<br><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"> v i遍历到这儿了</span><br><span class="line">i = 1 2 3 4 5 6 7 8 9 10 11 12</span><br><span class="line">a = 3 2 5 3 3 2 5 3 3 2 5 3</span><br><span class="line">ans = 0 0 3 0 0 0 0 0 0 0 0 0</span><br><span class="line"> ^答案被更新</span><br></pre></td></tr></table></figure></p><p>第二步:把遍历到的元素放进单调队列。当然,为了保持单调,也许需要弹出队尾的一些元素。</p><p><strong>其实这也是为什么不能用队列长度来更新答案的原因。有些数可能会被弹掉,此时直接用队列长度判断答案可能会遗漏。</strong></p><p>遍历完数组之后就可以输出答案了,但是有个问题:</p><p>比如样例遍历完之后 <code>ans</code> 数组长这样:</p><p><code>0 0 3 0 0 0 3 0 0 0 3 0</code></p><p>那 $1,2,4$ 号怎么办呢?</p><p>其实这个很简单,你想一下,就以 $2$ 号歌曲举例,你先听一首到 $3$ 号歌曲,然后再按照 $3$ 号的答案计算不就行了吗?所以这里我们再倒序遍历一遍数组,如果某个下标的答案没被更新,就把答案更新为 <code>在它后面的最近的一个本来就有答案的值 + 当前遍历到的下标和那个数的下标之差</code>。</p><p>给出代码:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><deque></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>)<span class="number">3e5</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, N, a[maxn], ans[maxn];</span><br><span class="line">std::deque<<span class="type">int</span>> q;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">file</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">freopen</span>(<span class="string">"playlist.in"</span>, <span class="string">"r"</span>, stdin);</span><br><span class="line"> <span class="built_in">freopen</span>(<span class="string">"playlist.out"</span>, <span class="string">"w"</span>, stdout);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">file</span>();</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &a[i]);</span><br><span class="line"> a[i + n] = a[i + (n << <span class="number">1</span>)] = a[i];</span><br><span class="line"> }</span><br><span class="line"> N = <span class="number">3</span> * n;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, N) {</span><br><span class="line"> <span class="keyword">while</span>(!q.<span class="built_in">empty</span>()<span class="comment">/*防止 RE*/</span> && (a[i] << <span class="number">1</span>) < a[q.<span class="built_in">front</span>()]) {</span><br><span class="line"> ans[q.<span class="built_in">front</span>()] = i - q.<span class="built_in">front</span>();</span><br><span class="line"> q.<span class="built_in">pop_front</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">while</span>(!q.<span class="built_in">empty</span>() && a[q.<span class="built_in">back</span>()] < a[i])</span><br><span class="line"> q.<span class="built_in">pop_back</span>();</span><br><span class="line"> q.<span class="built_in">push_back</span>(i);</span><br><span class="line"> }</span><br><span class="line"> <span class="type">int</span> tot = <span class="number">0</span>, lst = N + <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">dep</span>(i, N, <span class="number">1</span>) {</span><br><span class="line"> <span class="keyword">if</span>(ans[i]) {</span><br><span class="line"> tot = <span class="number">0</span>;</span><br><span class="line"> lst = i;</span><br><span class="line"> } <span class="keyword">else</span></span><br><span class="line"> ans[i] = ans[lst] + tot;</span><br><span class="line"> ++tot;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d "</span>, (ans[i] < n << <span class="number">1</span>) ? ans[i] : <span class="number">-1</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h3 id="T2"><a href="#T2" class="headerlink" title="T2"></a>T2</h3><p>二分很明显,关键是 $\text{check}$ 函数怎么写。</p><p>这里我们用 dp:$dp_{i,j}$ 代表用了 $i$ 次红色,$j$ 次绿色最多能覆盖到的神坛的编号(注意这个编号及以前的所有神坛都需要被覆盖)。</p><p>但是有一个问题:$r,g$ 的范围是 $10^9$,这样难道不会炸掉吗?</p><p>这里需要注意一下,因为 $n\le 2000$,所以只要 $r+g\ge 2000$,答案就一定是 $1$,直接输出即可。</p><p>那么我们就人为地把 $r,g$ 的范围降到了 $2000$。<del>然后就可以开始愉快的 $\Theta(n^2)$ 啦!(口胡)</del></p><p>首先我们要想一下这个状态转移方程。假设我们这一次要用红色,那么我们要依托 $dp_{i-1,j}$ 的值,假设它为 $k$。我们已经覆盖到了第 $k$ 个神坛,所以,我们可以忽略第 $k$ 个和第 $k+1$ 个之间的那些空的坐标,直接把第 $k+1$ 个神坛作为左端点。</p><p>那右端点可以覆盖到哪里呢?这个需要预处理一下。我们设 $R_i$ 代表用红色的线段(长度为 $L$,就是我们需要 $\text{check}$ 的那个数),把第 $i$ 个神坛作为左端点,右端点能够覆盖的最大神坛编号,这个数是固定的。</p><p>至于怎么预处理,因为 $n$ 很小,$\Theta(n)$ 和 $\Theta(n^2)$ 都可以用。$\Theta(n)$ 就是用两个指针,先全都指着 $1$,然后一点一点往右走,保证两个指针之间的区间长度不超过 $L$ 但是最长,这样计算答案就可以了。</p><p>绿色同理,只不过是把 $L$ 换成 $2\times L$,$R$ 换成 $G$。</p><p>状态转移方程:</p><script type="math/tex; mode=display">dp_{i,j}=\max\{R_{dp_{i-1,j}+1},G_{dp_{i,j-1}+1}\}</script><p>当然,如果你直接这么写的话会愉快的 WA 掉。</p><p>注意初始化:$dp$ 极小值,$dp_{0,0}=0$,且枚举需要从 $0$ 开始(注意有 $0$ 的时候需要特殊判断)。</p><p>然后还是 WA……</p><p>注意状态转移方程,这个方程可能会访问到 $R/G_{n+1}$,所以我们还需要一句:$G_{n+1}←n,R_{n+1}←n$。</p><p>然后就没了。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><algorithm></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = <span class="number">2005</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, r, g, a[maxn];</span><br><span class="line"><span class="type">int</span> R[maxn], G[maxn], dp[maxn][maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">file</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">freopen</span>(<span class="string">"light.in"</span>, <span class="string">"r"</span>, stdin);</span><br><span class="line"> <span class="built_in">freopen</span>(<span class="string">"light.out"</span>, <span class="string">"w"</span>, stdout);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">bool</span> <span class="title">check</span><span class="params">(<span class="type">int</span> L)</span> </span>{</span><br><span class="line"> <span class="built_in">memset</span>(dp, <span class="number">-0x3f</span>, <span class="built_in">sizeof</span>(dp));</span><br><span class="line"> dp[<span class="number">0</span>][<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line"> <span class="type">int</span> p = <span class="number">1</span>, q = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span>(p <= n) {</span><br><span class="line"> <span class="keyword">while</span>(q <= n && a[q] - a[p] + <span class="number">1</span> <= L)</span><br><span class="line"> ++q;</span><br><span class="line"> R[p] = q - <span class="number">1</span>;</span><br><span class="line"> ++p;</span><br><span class="line"> }</span><br><span class="line"> p = <span class="number">1</span>, q = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span>(p <= n) {</span><br><span class="line"> <span class="keyword">while</span>(q <= n && a[q] - a[p] + <span class="number">1</span> <= L << <span class="number">1</span>)</span><br><span class="line"> ++q;</span><br><span class="line"> G[p] = q - <span class="number">1</span>;</span><br><span class="line"> ++p;</span><br><span class="line"> }</span><br><span class="line"> G[n + <span class="number">1</span>] = R[n + <span class="number">1</span>] = n;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">0</span>, r) {</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">0</span>, g) {</span><br><span class="line"> <span class="keyword">if</span>(!i && !j)</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(!i)</span><br><span class="line"> dp[i][j] = G[dp[i][j - <span class="number">1</span>] + <span class="number">1</span>];</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(!j)</span><br><span class="line"> dp[i][j] = R[dp[i - <span class="number">1</span>][j] + <span class="number">1</span>];</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> dp[i][j] = std::<span class="built_in">max</span>(R[dp[i - <span class="number">1</span>][j] + <span class="number">1</span>], G[dp[i][j - <span class="number">1</span>] + <span class="number">1</span>]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> dp[r][g] >= n;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">f</span><span class="params">(<span class="type">int</span> l, <span class="type">int</span> r)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(l == r)</span><br><span class="line"> <span class="keyword">return</span> l;</span><br><span class="line"> <span class="type">int</span> mid = (l + r) >> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span>(<span class="built_in">check</span>(mid))</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">f</span>(l, mid);</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">f</span>(mid + <span class="number">1</span>, r);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">file</span>();</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d %d"</span>, &n, &r, &g);</span><br><span class="line"> <span class="keyword">if</span>(r + g >= n) {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"1"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &a[i]);</span><br><span class="line"> std::<span class="built_in">stable_sort</span>(a + <span class="number">1</span>, a + n + <span class="number">1</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d"</span>, <span class="built_in">f</span>(<span class="number">1</span>, <span class="number">1000000000</span>));</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h3 id="T3"><a href="#T3" class="headerlink" title="T3"></a>T3</h3><p><del>思维题诶!全场 AC 人数最少的一道题。</del></p><p>首先看数据范围,$1\le n\le 10^9$,肯定不能用 $n$ 来枚举 <del>(毕竟 mjl 测评不开 O2)</del>。</p><p>那我们再思考一下,发现 $1\le m\le 10^5$,可以用 $m$ 来枚举。所以我们可以求一下:以每一个公共牌作为顺牌中第一张公共牌的方案数。</p><p>这样想有一个好处:不用去重。因为只要第一张公共牌不一样,那么两种方案肯定不同;而求一种情况时也不会重复计算。</p><p>那么怎么算呢?我们可以求出此时这个顺牌区间左端点能够覆盖到的最小和最大值,然后再减一下不就行了吗。</p><p>那这个最值怎么算呢?假设现在需要求的牌编号为 $i$。</p><p>先说最小值吧:</p><p>首先我们把给出的公共牌排序、去重。<strong>众所周知,数组去了重之后不一定和原来数组一样长,所以,我们现在用 $m$ 代表顺牌区间的长度,$k$ 代表去重后公共牌的个数,切勿混淆。</strong></p><p>第一点,因为 $i$ 是顺牌序列中的第一张公共牌,所以,顺牌的开头必须比第 $i-1$ 张公共牌的数值更大,即 $a_{i-1}+1$。</p><p>第二点,因为要形成连续 $m$ 张顺牌,而个人牌只有 $s$ 张,<strong>所以这个连续的序列里必须包含至少 $\bf{m-s}$ 张公共牌。</strong> 而 $i$ 是第一张,所以还要往后继续找至少 $m-s-1$ 张公共牌,而在规定条件下,找得越少,顺牌的开始位置就越靠前,这也是我们要找的最小值。从第 $i$ 张牌开始,往后找 $m-s-1$ 张牌是第 $i+m-s-1$ 张,再往前找开头,往前再找 $m$ 个就可以了。</p><p>这两个条件必须<strong>同时满足</strong>,所以在计算最小值时取这两个的最大值,即:</p><script type="math/tex; mode=display">Min=\max\{a_{i-1}+1,a_{i+m-s-1}-m+1\}</script><p>最大值要简单一些,因为要包含这张牌,所以最多到 $a_i$;而且因为顺牌的个数是 $m$ 张,所以要保证这么多牌,开头不能超过 $n-m+1$。取这两者的最小值即可。</p><p>这里需要注意一点,有时最小值可能反而比最大值大,此时是无解的,不要加上一个负数。</p><p>代码倒是挺简洁。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><algorithm></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>)<span class="number">1e5</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m, s, ans, a[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">max</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <span class="keyword">return</span> x > y ? x : y; }</span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">min</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <span class="keyword">return</span> x < y ? x : y; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">file</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">freopen</span>(<span class="string">"straight.in"</span>, <span class="string">"r"</span>, stdin);</span><br><span class="line"> <span class="built_in">freopen</span>(<span class="string">"straight.out"</span>, <span class="string">"w"</span>, stdout);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">file</span>();</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d %d"</span>, &n, &m, &s);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, m)</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &a[i]);</span><br><span class="line"> std::<span class="built_in">stable_sort</span>(a + <span class="number">1</span>, a + m + <span class="number">1</span>);</span><br><span class="line"> <span class="type">int</span> k = std::<span class="built_in">unique</span>(a + <span class="number">1</span>, a + m + <span class="number">1</span>) - a - <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, k - m + s + <span class="number">1</span>) {</span><br><span class="line"> <span class="type">int</span> Min = <span class="built_in">max</span>(a[i - <span class="number">1</span>] + <span class="number">1</span>, a[i + m - s - <span class="number">1</span>] - m + <span class="number">1</span>);</span><br><span class="line"> <span class="type">int</span> Max = <span class="built_in">min</span>(a[i], n - m + <span class="number">1</span>);</span><br><span class="line"> ans += <span class="built_in">max</span>(<span class="number">0</span>, Max - Min + <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d"</span>, ans);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h3 id="T4"><a href="#T4" class="headerlink" title="T4"></a>T4</h3><p><del>先纠正一个错误:DNA 是两条,这玩意儿应该是 RNA 但是又要换一个字母……</del></p><p>这题的突破口是 $|e|$ 和字母种类都很小,字母只有四种。</p><p>我们先写一个函数 $\text{f(ch)}$,可以把不同的字母转换为不同的下标($eg.\ A\to 0,T\to 1,G\to 2,C\to 3$),这样可以使代码更加方便。</p><p>然后看一下这个序列,如果要从某一个字母开始周期修改,假设周期的长度是 $len$,某个字符在周期(也就是 $e$)中的位置是 $i$,我们会发现一件有趣的事,如图:</p><p><img src="https://s2.loli.net/2022/01/11/7ozaY4KsivOwFH8.png" alt=""></p><p>红色的地方即为这个字符会修改到的地方,可以发现这个分部是有规律的,它所有能够修改到的字符的下标 $\bmod\ len$ 的结果是一样的。</p><p>所以我们可以令 $BIT_{i,ch,j,k}$ 来代表字符为 $ch$,周期长度为 $j$ 且在周期中的位置为 $k$(周期遍历从 $1$ 开始),所有满足这些条件的字符在 $1\sim i$ 这个范围中的个数。</p><p>然后就是板子了。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>)<span class="number">1e5</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m, len;</span><br><span class="line"><span class="type">char</span> s[maxn], e[<span class="number">15</span>];</span><br><span class="line"><span class="type">int</span> BIT[maxn][<span class="number">4</span>][<span class="number">11</span>][<span class="number">11</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">lowbit</span><span class="params">(<span class="type">int</span> x)</span> </span>{ <span class="keyword">return</span> x & -x; }</span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">min</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <span class="keyword">return</span> x < y ? x : y; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">f</span><span class="params">(<span class="type">char</span> c)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(c == <span class="string">'A'</span>)</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(c == <span class="string">'T'</span>)</span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(c == <span class="string">'G'</span>)</span><br><span class="line"> <span class="keyword">return</span> <span class="number">2</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="number">3</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">update</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> k, <span class="type">char</span> c, <span class="type">int</span> p, <span class="type">int</span> id)</span> </span>{</span><br><span class="line"> <span class="type">int</span> l = <span class="built_in">f</span>(c);</span><br><span class="line"> <span class="keyword">while</span>(x <= n) {</span><br><span class="line"> BIT[x][l][p][id] += k;</span><br><span class="line"> x += <span class="built_in">lowbit</span>(x);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">query</span><span class="params">(<span class="type">int</span> x, <span class="type">char</span> c, <span class="type">int</span> p, <span class="type">int</span> id)</span> </span>{</span><br><span class="line"> <span class="type">int</span> sum = <span class="number">0</span>, l = <span class="built_in">f</span>(c);</span><br><span class="line"> <span class="keyword">while</span>(x) {</span><br><span class="line"> sum += BIT[x][l][p][id];</span><br><span class="line"> x -= <span class="built_in">lowbit</span>(x);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> sum;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">file</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">freopen</span>(<span class="string">"virus.in"</span>, <span class="string">"r"</span>, stdin);</span><br><span class="line"> <span class="built_in">freopen</span>(<span class="string">"virus.out"</span>, <span class="string">"w"</span>, stdout);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">file</span>();</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%s"</span>, s + <span class="number">1</span>);</span><br><span class="line"> n = <span class="built_in">strlen</span>(s + <span class="number">1</span>);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">1</span>, <span class="number">10</span>)</span><br><span class="line"> <span class="built_in">update</span>(i, <span class="number">1</span>, s[i], j, i % j);</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &m);</span><br><span class="line"> <span class="type">int</span> op, x, l, r;</span><br><span class="line"> <span class="type">char</span> c;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, m) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &op);</span><br><span class="line"> <span class="keyword">if</span>(op == <span class="number">1</span>) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %c"</span>, &x, &c);</span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">1</span>, <span class="number">10</span>) {</span><br><span class="line"> <span class="built_in">update</span>(x, <span class="number">1</span>, c, j, x % j);</span><br><span class="line"> <span class="built_in">update</span>(x, <span class="number">-1</span>, s[x], j, x % j);</span><br><span class="line"> }</span><br><span class="line"> s[x] = c;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d %s"</span>, &l, &r, e + <span class="number">1</span>);</span><br><span class="line"> len = <span class="built_in">strlen</span>(e + <span class="number">1</span>);</span><br><span class="line"> <span class="type">int</span> ans = <span class="number">0</span>;</span><br><span class="line"> <span class="comment">// 这里注意一下应该是 (l + j - 1) % len 而不是 j,因为我们定义的周期遍历是从 1 而非从 l 开始 </span></span><br><span class="line"> <span class="built_in">rep</span>(j, <span class="number">1</span>, <span class="built_in">min</span>(len, r - l + <span class="number">1</span>))</span><br><span class="line"> ans += <span class="built_in">query</span>(r, e[j], len, (l + j - <span class="number">1</span>) % len) - <span class="built_in">query</span>(l - <span class="number">1</span>, e[j], len, (l + j - <span class="number">1</span>) % len);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d\n"</span>, ans);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>这次考试爆炸了,$0+10+0+0$ 差点就保龄了……</p><p>T1 我打了一个线段树,结果没有调出来,T2 写了二分+贪心就没管了,T3 和 T4 都没有写出一个像样的代码……</p><p>只能说明思维和码力都太弱了 qwq。</p><p>以及,一定不要拘泥于才学过的知识点(话说我 T3 刚开始也打的线段树来着 qwq)。</p>]]></content>
<summary type="html">记一次完全炸掉的考试</summary>
<category term="考试总结" scheme="https://blog.liynw.top/categories/%E8%80%83%E8%AF%95%E6%80%BB%E7%BB%93/"/>
<category term="动态规划" scheme="https://blog.liynw.top/tags/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/"/>
<category term="数据结构" scheme="https://blog.liynw.top/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
<category term="二分答案" scheme="https://blog.liynw.top/tags/%E4%BA%8C%E5%88%86%E7%AD%94%E6%A1%88/"/>
<category term="单调队列" scheme="https://blog.liynw.top/tags/%E5%8D%95%E8%B0%83%E9%98%9F%E5%88%97/"/>
<category term="思维" scheme="https://blog.liynw.top/tags/%E6%80%9D%E7%BB%B4/"/>
</entry>
<entry>
<title>ST 表求解 RMQ 问题</title>
<link href="https://blog.liynw.top/posts/51bfc0ec/"/>
<id>https://blog.liynw.top/posts/51bfc0ec/</id>
<published>2022-01-26T22:57:12.000Z</published>
<updated>2022-02-20T11:45:35.000Z</updated>
<content type="html"><![CDATA[<h2 id="1-RMQ-是啥"><a href="#1-RMQ-是啥" class="headerlink" title="1. RMQ 是啥"></a>1. RMQ 是啥</h2><blockquote><p>RMQ (Range Minimum / Maximum Query)问题是指:对于长度为 $n$ 的数列 $A$,回答若干询问 $\text{RMQ}(A,i,j)(1\leq i,j\leq n)$,返回数列 $A$ 中下标在 $[i,j]$ 里的最小(大)值,<strong>也就是说,RMQ 问题是指求区间最值的问题。</strong></p></blockquote><p><del>全是抄的。</del></p><p>也就是说,RMQ 是一类问题,而不是一类数据结构。</p><p>所以<del>暴力(没有初始化,查询$\Theta(n)$)</del>,线段树(初始化和查询都是 $\Theta(\log n)$)等都可以解决 RMQ 问题。</p><p>那么是否有更♂快的方法呢?</p><p>有!就是 <strong>ST 表</strong>。</p><hr><h2 id="2-概念"><a href="#2-概念" class="headerlink" title="2. 概念"></a>2. 概念</h2><p>ST 表通过 DP 的方式,可以实现 $\Theta(n\log n)$ 初始化,$\Theta(1)$ 查询区间最值。</p><p>优点:最重要的,快!</p><p>缺点:不支持修改数组,而且空间复杂度为 $\Theta(n\log n)$,可能会受不了。</p><hr><h2 id="3-实现"><a href="#3-实现" class="headerlink" title="3. 实现"></a>3. 实现</h2><p>$dp_{i,j}$ 代表从 $i$ 开始,区间长度为 $2^j$ 的区间,即 $[i,i+2^j)$ 的最值(可以是最大值或者最小值,这个无所谓)。</p><h3 id="初始化"><a href="#初始化" class="headerlink" title="初始化"></a>初始化</h3><p>对于 $\forall i,j=0$ 时,区间只有 $A_i$ 这一个数字,所以肯定最值是 $A_i$。</p><script type="math/tex; mode=display">dp_{i,0}=A_i(1\leq i\le n)</script><h3 id="状态转移"><a href="#状态转移" class="headerlink" title="状态转移"></a>状态转移</h3><p>我们知道,对于任意一个长度为 $2$ 的幂次方的区间,都可以划分为长度相等的两部分,例如 $[3,10]$ 就像这样:</p><p>($i=3,j=3$)</p><p><img src="https://img-blog.csdnimg.cn/4d23757e51bb42279587a7bf8147d76d.png" alt=""></p><p>也可以说明区间 $[i,i+2^j)$ 可以被分为 $[i,i+2^{j-1})$ 和 $[i+2^{j-1},i+2^j)$ 两个部分,每个部分的长度都是 $2^{j-1}$。</p><p>那么转移方程不就出来了吗:</p><script type="math/tex; mode=display">dp_{i,j}=\max(or \min)\{dp_{i,j-1},dp_{i+2^{j-1},j-1}\}</script><p>当然,在代码的实现过程中,我们可以用 <code>1 << x</code> 来代替分析中的 $2^x$,不过需要注意的是,位运算的优先级比四则运算低,需要打括号。</p><h3 id="查询"><a href="#查询" class="headerlink" title="查询"></a>查询</h3><p>对于任意一个区间 $[i,j]$,如何用已经初始化好的 ST 表求解最值呢?</p><p>看图:</p><p><img src="https://img-blog.csdnimg.cn/e5bfd2ed96774760851a0bd61d305897.png" alt=""></p><p>我们可以把任意一个区间分解成这样两个长度为 $2$ 的幂次的区间,一个区间左端点为待求区间的左端点,另一个区间的右端点为待求区间的右端点,两个区间的长度为所有 $2$ 的幂次中小于 $j-i+1$ 的最大的那一个,转换一下就变成了可以用 $2$ 的幂次表示的 $2^{\lfloor\log_2(j-i+1)\rfloor}$。(PS:$2^{\log_2(x)}=x$)。</p><p>找到两个分解后的区间,求一下最值就行了。</p><hr><p>数列区间最大值问题:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cmath></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rep(i, j, k) for(int i = j; i <= k; ++i)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> dep(i, j, k) for(int i = j; i >= k; --i)</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>)<span class="number">1e5</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, q, a[maxn], dp[maxn][<span class="number">1005</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">max</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <span class="keyword">return</span> x > y ? x : y; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">init</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> dp[i][<span class="number">0</span>] = a[i];</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">1</span>; <span class="number">1</span> << j <= n; ++j)</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i + (<span class="number">1</span> << j - <span class="number">1</span>) - <span class="number">1</span> <= n; ++i)</span><br><span class="line"> dp[i][j] = <span class="built_in">max</span>(dp[i][j - <span class="number">1</span>], dp[i + (<span class="number">1</span> << j - <span class="number">1</span>)][j - <span class="number">1</span>]);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">rmq</span><span class="params">(<span class="type">int</span> l, <span class="type">int</span> r)</span> </span>{</span><br><span class="line"> <span class="type">int</span> k = <span class="built_in">log2</span>(r - l + <span class="number">1</span>); <span class="comment">// cmath 库中有内置的 log2 函数,请注意不要用成以 e 为底的 log 函数</span></span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">max</span>(dp[l][k], dp[r - (<span class="number">1</span> << k) + <span class="number">1</span>][k]);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &n, &q);</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, n)</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &a[i]);</span><br><span class="line"> <span class="built_in">init</span>();</span><br><span class="line"> <span class="type">int</span> l, r;</span><br><span class="line"> <span class="built_in">rep</span>(i, <span class="number">1</span>, q) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &l, &r);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d\n"</span>, <span class="built_in">rmq</span>(l, r));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">} </span><br></pre></td></tr></table></figure><hr><h2 id="4-应用"><a href="#4-应用" class="headerlink" title="4. 应用"></a>4. 应用</h2><p>ST 表本身就是个工具,我们在平时做题的时候不能想着刻意去使用它,详情参考洛谷 <a href="https://www.luogu.com.cn/problem/P2048">P2048</a> 。</p><p>另外,ST 表之所以有局限性,是因为它在查询的时候可能会有一部分区间被重复查询,所以只能求解那些有重复元素不影响最终结果的问题。这种问题除了最大最小值之外,还有 gcd、lcm 等,所以这些问题也是可以通过 ST 表求的。</p>]]></content>
<summary type="html">讲 ST 表那天不是 mjl 上的课,那个老师一直把 ST 表讲成 RMQ……</summary>
<category term="学习笔记" scheme="https://blog.liynw.top/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<category term="动态规划" scheme="https://blog.liynw.top/tags/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/"/>
</entry>
<entry>
<title>线段树</title>
<link href="https://blog.liynw.top/posts/8893d943/"/>
<id>https://blog.liynw.top/posts/8893d943/</id>
<published>2022-01-26T22:54:55.000Z</published>
<updated>2022-02-01T10:03:46.000Z</updated>
<content type="html"><![CDATA[<h2 id="前置芝士"><a href="#前置芝士" class="headerlink" title="前置芝士"></a>前置芝士</h2><ul><li>二分的递归写法</li><li>二叉树</li></ul><hr><h2 id="线段树"><a href="#线段树" class="headerlink" title="线段树"></a>线段树</h2><p>线段树(Segment Tree)是一种二叉树,本质上和树状数组有区别<del>虽然都是树</del>。</p><p>不过和树状数组一样,线段树也是一种维护数组的数据结构,它可以实现 $O(\log n)$ 修改、查询<del>不过常数比树状数组大得多</del>。</p><p>另外,线段树的应用范围比树状数组广,不过它维护的数据必须满足结合律($eg.(a+b)+c=a+(b+c)$)。为什么呢?这涉及到线段树实现的原理。</p><hr><h3 id="性质-amp-原理"><a href="#性质-amp-原理" class="headerlink" title="性质 & 原理"></a>性质 & 原理</h3><p>首先要建一棵线段树,首先我们要有一个线段,那就是数组。</p><p>然后,我们还需要一棵二叉树。</p><p>于是,我们就成功种了一棵线段树。</p><p>它长这样:</p><p><img src="https://s2.loli.net/2021/12/06/mN5Aro4wzDGBykP.jpg" alt=""></p><p>注意到每个结点里面的区间没,这是闭区间,代表的是这个结点存的信息来源于数组的哪个区间。</p><p>观察这个线段树,我们可以发现:</p><ul><li>每个叶子结点都代表数组中的一个元素。</li><li><p>每个非叶子结点的两个孩子的区间是从父节点区间的中间划开的。</p><p> 说详细一点,若一个非叶子结点覆盖的区间为 $[L,R]$,那么令 $mid=\lfloor \frac{L-R}{2}\rfloor$,则左孩子覆盖的区间为 $[L,mid]$,右孩子覆盖的区间为 $[mid+1,R]$。</p></li><li>除去最后一行是一棵满二叉树。</li></ul><p>那线段树的原理是怎样的呢?这里我们先讲最简单的单点修改、区间查询来理解。</p><p>有点类似于于归并排序,我们需要<strong>分解后再合并数据</strong>。每个父节点存储的信息都是其两个子节点信息的合并,这样我们就可以通过访问一个结点拿到这个节点所代表区间的信息。</p><p>首先分解,我们一层一层往下递归,直到找到叶子结点,然后把叶子结点的信息向它的父节点传递:</p><p><img src="https://s2.loli.net/2021/12/06/391XHMCVrvPwnjI.jpg" alt="向上传递信息"></p><p>然后由于递归回溯的原因,我们会接着遍历到它的兄弟,这个时候,它的父节点已经获得了两个子节点的信息,就可以<strong>合并信息</strong>了。</p><p>这个地方,我们给数组一个值,然后用数组元素和来代表需要求解的信息。</p><p><img src="https://s2.loli.net/2021/12/06/FnDj4KopWGSmB8P.jpg" alt="赋值"></p><p>我们继续往上回溯,按照相同的方法求解。在求解 $[1,3]$ 之前,我们需要把 $[1,2]$ 的值先传上去。</p><p><img src="https://s2.loli.net/2021/12/06/mgvj1z5rhweiLGW.jpg" alt="再往上"></p><p>这么一点一点的传上去,就可以求得区间的和了!</p><p>这个操作的时间复杂度是 $O(\log n)$,每次修改、查询和初始化的时候都这么来一遍,不就可以实现单点修改区间查询了嘛。</p><p>那么为什么求得的值必须满足结合律呢?显而易见,我们需要把求解的值分成一个区域一个区域地求解,如果不满足结合律就会出问题。</p><p>接下来我们来讲一讲 C++ 的实现。</p><hr><h3 id="存储"><a href="#存储" class="headerlink" title="存储"></a>存储</h3><p>于是我们知道,每一个结点里需要存:</p><ul><li>区间左端点 $l$</li><li>区间右端点 $r$</li><li>这个区间的信息($eg.\sum_{i=l}^{r}a_i$ 或者 $\max^{r}_{i=l}{a_i}$)</li></ul><p>等等,为什么不用存左孩子和右孩子呢?</p><p>这就涉及到存储线段树的方法。</p><p>一般来说,只要题目不卡空间,我们可以通过数组来存一个本质上是二叉树的线段树:</p><p>根节点数组下标是 $1$,对于每个非叶子节点,若它的数组下标是 $p$,那么其左孩子数组下标是 $2p$,右孩子数组下标是 $2p+1$。</p><p>那么,处理好存储的问题,接下来我们来解决初始化。</p><hr><h3 id="初始化-amp-单点修改"><a href="#初始化-amp-单点修改" class="headerlink" title="初始化 & 单点修改"></a>初始化 & 单点修改</h3><p>对于一段区间 $[l,r]$,我们把它从 $mid$ 分成 $[l,mid]$ 和 $[mid+1,r]$,然后以这两个区间作为此结点的两个子节点。</p><p>像开头说的那样,我们一直往下递归,当递归到叶子结点的时候就把数组的值赋给叶子结点,接着我们把叶子结点的信息传到它的父结点,然后求父结点的值,再把父结点的信息传给父结点的父结点……最终就可以把信息传递到根节点了。</p><p>请注意,儿子向父亲转移需要放在递归语句的后面。除此之外没有什么别的难点,看代码:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 这两行代码是求左子树和右子树下标的函数,p << 1 等价于 p * 2,p << 1 | 1 等价于 p * 2 + 1,不过速度更快</span></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">lc</span><span class="params">(<span class="type">int</span> p)</span> </span>{ <span class="keyword">return</span> p << <span class="number">1</span>; }</span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">rc</span><span class="params">(<span class="type">int</span> p)</span> </span>{ <span class="keyword">return</span> p << <span class="number">1</span> | <span class="number">1</span>; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">build</span><span class="params">(<span class="type">int</span> p, <span class="type">int</span> l, <span class="type">int</span> r)</span> </span>{</span><br><span class="line"> t[p].l = l, t[p].r = r; <span class="comment">// 给结点代表的区间端点赋值</span></span><br><span class="line"> <span class="keyword">if</span>(l == r) { <span class="comment">// 这个节点是叶子节点,没有子树</span></span><br><span class="line"> t[p].val = a[l]; <span class="comment">// 赋值</span></span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="type">int</span> mid = (l + r) >> <span class="number">1</span>;</span><br><span class="line"> <span class="built_in">build</span>(<span class="built_in">lc</span>(p), l, mid); <span class="comment">// 初始化左子树</span></span><br><span class="line"> <span class="built_in">build</span>(<span class="built_in">rc</span>(p), mid + <span class="number">1</span>, r); <span class="comment">// 初始化右子树</span></span><br><span class="line"> t[p].val = t[<span class="built_in">lc</span>(p)].val + t[<span class="built_in">rc</span>(p)].val; <span class="comment">// 合并左右子树的信息</span></span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><p>单点修改的代码和初始化很像,不过还是有一点区别。</p><p>假设我们要修改下标为 $3$ 的数字,把它加上 $5$:</p><p><img src="https://s2.loli.net/2021/12/24/lFYhgs42vHINSUQ.jpg" alt=""></p><p>就像这样,我们要在每一个包含所修改数据的下标的区间加上 $5$。</p><p>那么整个 $\text{update}$ 函数有这两个部分:</p><ol><li><p>从根节点出发往下找,直到找到需要修改的点(叶子节点);</p></li><li><p>往上回溯过程中修改每一个经过的结点的值。</p></li></ol><p>那么代码就呼之欲出了:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">update</span><span class="params">(<span class="type">int</span> p, <span class="type">int</span> x, <span class="type">int</span> k)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(t[p].l == t[p].r) { <span class="comment">// 找到了需要修改的叶子节点</span></span><br><span class="line"> t[p].val = k; <span class="comment">// 修改它的值</span></span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="type">int</span> mid = (t[p].l + t[p].r) >> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span>(mid >= x) <span class="comment">// 如果需要修改的结点在左子树</span></span><br><span class="line"> <span class="built_in">update</span>(<span class="built_in">lc</span>(p), x, k);</span><br><span class="line"> <span class="keyword">else</span> <span class="comment">// 需要修改的结点在右子树</span></span><br><span class="line"> <span class="built_in">update</span>(<span class="built_in">rc</span>(p), x, k);</span><br><span class="line"> t[p].val = t[<span class="built_in">lc</span>(p)].val + t[<span class="built_in">rc</span>(p)].val; <span class="comment">// 合并左右子树的信息</span></span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h3 id="区间查询"><a href="#区间查询" class="headerlink" title="区间查询"></a>区间查询</h3><p>我们可以找一些结点,且这些结点的范围能够<strong>刚好覆盖</strong>需要查询的区间,把这些结点的权值合并就可以了。</p><p>那怎么找呢?我们来看一张图:</p><p><img src="https://s2.loli.net/2022/02/26/URyjsDokYbW9EO5.jpg" alt=""></p><p>这张图是我们在查询区间 $[3,7]$ 时的过程。</p><p>在递归的时候,有以下几条准则:</p><ol><li>如果当前区间能<strong>完全被待查区间包含</strong>,就返回此区间的权值并不再往下递归。(图中打勾的地方)</li><li>如果当前区间被待查区间<strong>部分包含</strong>,就继续往下递归。</li><li>如果发现当前区间<strong>完全不能被当前区间包含</strong>,就停止递归。</li></ol><p>当然,这里还有个难点,就是怎么判断是否应该递归到某个结点的左子树或者右子树呢?</p><p>我们都知道,线段树中两个子节点的区间是从父节点区间的中间切开的。所以,如果要判断左子树是否需要递归,就应该这样:</p><p><img src="https://s2.loli.net/2022/02/26/3vCpAxhwmBEXf1y.png" alt=""></p><p>假设待查询区间是 $[L,R]$,我们会发现,只有在 $L\le mid$ 时,左区间才会被(至少是部分)包含。</p><p>右区间同理:</p><p><img src="https://s2.loli.net/2022/02/26/uI5vHSVEmecKify.png" alt=""></p><p>需要满足的条件是 $R\ge mid+1$,也就是 $R>mid$。</p><p>代码长这样:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">query</span><span class="params">(<span class="type">int</span> p, <span class="type">int</span> l, <span class="type">int</span> r)</span> </span>{</span><br><span class="line"> <span class="type">int</span> sum = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">if</span>(l <= t[p].l && t[p].r <= r)</span><br><span class="line"> <span class="keyword">return</span> t[p].val;</span><br><span class="line"> <span class="type">int</span> mid = (t[p].l + t[p].r) >> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span>(l <= mid)</span><br><span class="line"> sum += <span class="built_in">query</span>(<span class="built_in">lc</span>(p), l, r);</span><br><span class="line"> <span class="keyword">if</span>(r > mid)</span><br><span class="line"> sum += <span class="built_in">query</span>(<span class="built_in">rc</span>(p), l, r);</span><br><span class="line"> <span class="keyword">return</span> sum;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h3 id="区间修改"><a href="#区间修改" class="headerlink" title="区间修改"></a>区间修改</h3><p>众所周知单点修改线段树的时间复杂度是 $O(\log n)$,那么如果是区间修改,如何保持时间复杂度不变呢?</p><p>你可能会回答:差分。是的,这是一个可行的方法,不过差分只能维护区间和的查询,而对于查询最大值等则束手无策。<del>而且既然如此,直接打码量少常数小的树状数组他不香吗。</del></p><p>于是一个玄学的方法出现了:<strong>懒惰标记</strong>。</p><p>我们知道,对于一个区间的修改,后面的查询不一定用得到,比如有一次你修改区间 $[1,5]$ 但是后面根本没有查询这里的值,那么我们就没有必要在修改的时候把所有的子节点都修改一遍,<strong>只有需要的时候才修改。</strong></p><p>懒惰标记就是这么一个东西,我们给一个节点打上懒惰标记,就意味着<strong>这个结点的值已经被修改过,但是它的子节点还没有被更新。</strong> 只有我们在后面操作中需要更新后面的值,才需要把懒惰标记传到下面,更新需要的值。</p><p>在区间修改的时候,如果我们递归到一个结点覆盖的区间被需要修改的区间完全包含,那么我们就不需要再递归下去,而是给这个结点更新后打上一个懒惰标记,意味着这一段区间需要被修改,但是还没有完全实际操作。等下一次我们需要查询用到里面的值时,递归到这个节点时,我们就知道下面还没有更新,所以就把这个节点的两个子节点更新,然后把懒惰标记传到子节点上,以此类推。</p><p>把懒惰标记从父节点传到子节点的过程我们可以用一个 $\text{pushdown}$ 函数实现。在这个函数里面,我们先需要修改子节点的权值,然后把父节点的懒惰标记叠加到子节点的懒惰标记上,最后清空父节点的懒惰标记,代码如下:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// target 即为懒惰标记</span></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">down</span><span class="params">(<span class="type">int</span> p)</span> </span>{</span><br><span class="line"> <span class="type">int</span> l = <span class="built_in">lc</span>(p), r = <span class="built_in">rc</span>(p);</span><br><span class="line"> t[l].val += (t[l].r - t[l].l + <span class="number">1</span>) * t[p].target;</span><br><span class="line"> t[r].val += (t[r].r - t[r].l + <span class="number">1</span>) * t[p].target;</span><br><span class="line"> t[l].target += t[p].target;</span><br><span class="line"> t[r].target += t[p].target;</span><br><span class="line"> t[p].target = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h3 id="一些扩展"><a href="#一些扩展" class="headerlink" title="一些扩展"></a>一些扩展</h3><p>线段树不仅可以维护诸如区间和,最值之类,还可以维护一些奇奇怪怪的东西。</p><p>先来看第一组:</p><p><a href="https://www.luogu.com.cn/problem/SP1043">GSS1</a> <a href="https://www.luogu.com.cn/problem/SP1716">GSS3</a></p><p>要求的是一个区间的最大子段和。</p><p>想一下,把两个区间合并为一个区间,该怎么找到这个区间的最大子段和呢?</p><p>无非就三种情况嘛:</p><ol><li>左边的最大子段和;</li><li>右边的最大子段和;</li><li>左边<strong>包含右端点</strong>的最大子段和加上右边<strong>包含左端点</strong>的最大子段和。</li></ol><p>那这三个东西怎么求呢?</p>]]></content>
<summary type="html">关于某个人要在线段上种树这回事</summary>
<category term="学习笔记" scheme="https://blog.liynw.top/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<category term="数据结构" scheme="https://blog.liynw.top/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
</entry>
<entry>
<title>P7960 [NOIP2021] 报数 题解</title>
<link href="https://blog.liynw.top/posts/44375d99/"/>
<id>https://blog.liynw.top/posts/44375d99/</id>
<published>2021-12-04T15:46:18.000Z</published>
<updated>2021-12-04T15:48:21.000Z</updated>
<content type="html"><![CDATA[<p>蒟蒻抢到了 CCF 的题!</p><p>考场上打玄学复杂度还没处理 $10^7+1$ 的屑只得了 $70$ 分。</p><hr><p>首先,注意到所有<strong>包含 7 或者这些数的倍数</strong>都不可以报。那么我们可以利用一个类似于埃氏筛的东西来筛出这些不能报的数。</p><h3 id="什么是埃筛"><a href="#什么是埃筛" class="headerlink" title="什么是埃筛"></a>什么是埃筛</h3><p>埃氏筛法本来是用来找质数的一种质数筛法。</p><p>我们知道,一个质数只有 $1$ 和它本身两个因数,所以,我们可以通过任意两个不为 $1$ 的数相乘得到一个合数。</p><p>我们开一个数组 $b$,$b_i$ 代表 $i$ 是否为合数。从 $2$ 开始筛,如果此时 $b_i=0$,就说明这个数不能通过任意两个不为 $1$ 的数相乘得到,它是一个质数。</p><p>如果 $b_i=1$,说明这是一个合数。我们知道,任何一个数一定有至少一个因子是质数,所以每个数都可以通过让任意一个数和质数相乘得到。用合数再去与别的数相乘会浪费时间,所以我们需要直接跳过下面的步骤。</p><p>此时我们拿到了一个质数 $i$,然后我们开始遍历 $2\times i,3\times i,\ldots$,这些全部都是合数,所以把它们全部标记为合数,直到超出筛的范围。</p><p>代码很简单,大概长这样:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">Prime</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">2</span>; i * i <= n; i++) {</span><br><span class="line"> <span class="keyword">if</span>(f[i])</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">2</span> * i; j <= n; j += i)</span><br><span class="line"> f[j] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>时间复杂度大概是 $O(n\log \log n)$。</p><hr><h3 id="怎么做这道题"><a href="#怎么做这道题" class="headerlink" title="怎么做这道题"></a>怎么做这道题</h3><p>因为任何含有 $7$ 的数字或其倍数都不可以报出,所以我们可以通过乘积来筛掉所有不合法的数,这很明显是一道埃筛的变形。那么我们该如何做这道题呢?</p><p>我们还是开一个 $b$ 数组记录所有的数是否能报,其中 $b_i=0$ 代表 $i$ 可以报,$b_i=1$ 则不能。</p><p>首先我们要知道怎么判断一个数 $x$ 是否含有 $7$。这个很简单,只需要重复以下两个步骤:</p><ol><li>计算 $x/10$ 的余数是否等于 $7$,如果有,说明此数含有 $7$;</li><li>$x$ 除以 $10$。</li></ol><p>用这样的方法可以遍历到 $x$ 每个数位上的数。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 判断这个数能不能报,若 x 中有 7,返回 1 </span></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">bool</span> <span class="title">pan7</span><span class="params">(<span class="type">int</span> x)</span> </span>{</span><br><span class="line"> <span class="type">int</span> qwq;</span><br><span class="line"> <span class="keyword">while</span>(x) {</span><br><span class="line"> qwq = x % <span class="number">10</span>;</span><br><span class="line"> <span class="keyword">if</span>(qwq == <span class="number">7</span>)</span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"> x /= <span class="number">10</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>每次筛到一个不能报的数,因为其倍数也不能报,所以我们把它乘以不同的数,把这些数也标记为不能报。期间我们需要保证不筛到 $10^7+1$ 外面去。代码长这样:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">prime</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="keyword">if</span>(<span class="built_in">pan7</span>(i)) {</span><br><span class="line"> b[i] = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">1</span>; j <= n; j++) {</span><br><span class="line"> <span class="type">int</span> qwq = i * j;</span><br><span class="line"> <span class="keyword">if</span>(qwq > n)</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> b[qwq] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>时间复杂度 $O(n \log n)$。</p><p>接着我们已经知道了所有能报的的数,此时我们只需要从大到小遍历 $10^7+1\sim 1$ 的所有数,拿一个变量存当前遍历到的最小能报的数字,每次到一个数,这个变量里存的值就是它报了之后能报的下一个数字,把这个数存在 $ans$ 数组里面。</p><p>这样的预处理可以避免查询一个一个跳导致的玄学复杂度。</p><p>时间复杂度 $O(n)$。</p><p>然后我们就可以实现 $O(1)$ 询问。</p><hr><h3 id="一个坑"><a href="#一个坑" class="headerlink" title="一个坑"></a>一个坑</h3><p>题目数据范围是 $10^7$,为什么需要筛到 $10^7+1$ 呢?</p><p>因为可能询问的就是 $10^7$,而它的下一个数是 $10^7+1$。</p><p>这个坑卡掉了许许多多悲伤的 OIers。</p><hr><h3 id="Code"><a href="#Code" class="headerlink" title="Code"></a>Code</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cctype></span></span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>) <span class="number">1e7</span> + <span class="number">5</span>;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> n = maxn - <span class="number">4</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> t, q, tot, g[maxn], ans[maxn];</span><br><span class="line"><span class="type">bool</span> b[maxn];</span><br><span class="line"><span class="comment">// b[x] = 1 说明 x 不能被选</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 若 x中有 7,返回 1 </span></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">bool</span> <span class="title">pan7</span><span class="params">(<span class="type">int</span> x)</span> </span>{</span><br><span class="line"> <span class="type">int</span> qwq;</span><br><span class="line"> <span class="keyword">while</span>(x) {</span><br><span class="line"> qwq = x % <span class="number">10</span>;</span><br><span class="line"> <span class="keyword">if</span>(qwq == <span class="number">7</span>)</span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"> x /= <span class="number">10</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">prime</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="keyword">if</span>(<span class="built_in">pan7</span>(i)) {</span><br><span class="line"> b[i] = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">1</span>; j <= n; j++) {</span><br><span class="line"> <span class="type">int</span> qwq = i * j;</span><br><span class="line"> <span class="keyword">if</span>(qwq > n)</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> b[qwq] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 快读快写</span></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">read</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="type">int</span> x = <span class="number">0</span>, w = <span class="number">0</span>;</span><br><span class="line"> <span class="type">char</span> ch = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span>(!<span class="built_in">isdigit</span>(ch)) {</span><br><span class="line"> w |= ch == <span class="string">'-'</span>;</span><br><span class="line"> ch = <span class="built_in">getchar</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">while</span>(<span class="built_in">isdigit</span>(ch)) {</span><br><span class="line"> x = (x << <span class="number">3</span>) + (x << <span class="number">1</span>) + (ch ^ <span class="number">48</span>);</span><br><span class="line"> ch = <span class="built_in">getchar</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> w ? -x : x;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">write</span><span class="params">(<span class="type">int</span> x)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(x < <span class="number">0</span>) <span class="built_in">putchar</span>(<span class="string">'-'</span>), x = -x;</span><br><span class="line"> <span class="keyword">if</span>(x > <span class="number">9</span>) <span class="built_in">write</span>(x / <span class="number">10</span>);</span><br><span class="line"> <span class="built_in">putchar</span>(x % <span class="number">10</span> + <span class="string">'0'</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="comment">// freopen("number.in", "r", stdin);</span></span><br><span class="line"> <span class="comment">// freopen("number.out", "w", stdout);</span></span><br><span class="line"> <span class="built_in">prime</span>();</span><br><span class="line"> <span class="type">int</span> Ans = (<span class="type">int</span>) <span class="number">1e7</span> + <span class="number">1</span>; <span class="comment">// 必须 +1</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = n; i; i--) {</span><br><span class="line"> ans[i] = Ans;</span><br><span class="line"> <span class="keyword">if</span>(!b[i])</span><br><span class="line"> Ans = i;</span><br><span class="line"> }</span><br><span class="line"> t = <span class="built_in">read</span>();</span><br><span class="line"> <span class="keyword">while</span>(t--) {</span><br><span class="line"> q = <span class="built_in">read</span>();</span><br><span class="line"> <span class="built_in">write</span>(b[q] ? <span class="number">-1</span> : ans[q]);</span><br><span class="line"> <span class="built_in">putchar</span>(<span class="string">'\n'</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">NOIP T1 真的有这么简单吗?</summary>
<category term="题解" scheme="https://blog.liynw.top/categories/%E9%A2%98%E8%A7%A3/"/>
<category term="数学" scheme="https://blog.liynw.top/tags/%E6%95%B0%E5%AD%A6/"/>
</entry>
<entry>
<title>NOIP2021 爆炸记</title>
<link href="https://blog.liynw.top/posts/407315f9/"/>
<id>https://blog.liynw.top/posts/407315f9/</id>
<published>2021-12-04T15:42:48.000Z</published>
<updated>2022-01-30T17:11:39.000Z</updated>
<content type="html"><![CDATA[<h3 id="Day"><a href="#Day" class="headerlink" title="Day -?"></a>Day -?</h3><p>笑死,CQ 四百多名额最后去了三百多人(包括初中生)。</p><p>初二划水人员表示很淦。</p><hr><p>因为 CSP 完了就是《期 中 定 时 作 业》,所以暂时潜心搞 whk 没怎么搞 OI。</p><p>结果《期 中 定 时 作 业》爆炸了,语文估错时间作文没写完……</p><p>后来我们语文老师给我估分 $42$,我十分怀疑这个分数的真实性,但是我相信我们的语文老师 (^_^)。</p><p>数学海星,终于上 $140$ 了。英语比较爆炸,客观题扣了 $9$ 分,作文扣了 $4$ 分,勉强上 $135$,拿了本英语老师的英文版爱丽丝漫游仙境。<del>我们班最高 146,orz 年级第二 NH4+ 大佬。</del></p><p>最后结果嘛……班级 $\text{rk13(14?)}$,年级勉强卡进前 $100$。</p><hr><h3 id="Day-2、-1"><a href="#Day-2、-1" class="headerlink" title="Day -2、-1"></a>Day -2、-1</h3><p>一年一度的趣味运动会,初二了也是初中的最后一次。因为我们班妹子很少,而每个项目一个班男生和女生的参加人数是一样的,所以每个妹子都有很多项目。</p><p>我在那里颓废,看到班上一堆卷王在自己座位上卷,感到十分惊恐。<del>但是这依然挡不住我想要颓废的心(狗头)。</del></p><p>班级获得的结果还不错,拿了羊角球接力的第一名,最后<del>凭借“暗箱操作”的道德风尚奖</del>以 $5$ 分之差惊险拿到一等奖最后一名。(PS:后面我们班在冬季长跑以一分之差得到第二,英语配音二等奖第一名,都被我们说做这次的“报应”。)</p><p>本蒟蒻基本上在参加项目+看别人打排球+颓废+和 lym 聊天,没怎么复习(</p><hr><h3 id="Day-0"><a href="#Day-0" class="headerlink" title="Day 0"></a>Day 0</h3><p>梅开二度,又发遗照……我的考号是 CQ-00281,本来说是想和大佬面基,但是大佬都很忙,也不敢去问。</p><p>话说 CQ NOIP 要全程戴口罩?这对于一个一戴口罩眼镜就要起雾的人来说怕是不太友好哦(</p><p>晚上回家准备了一堆吃的,稍微看了一下考前注意事项就去睡觉了。</p><hr><h3 id="Day-1"><a href="#Day-1" class="headerlink" title="Day 1"></a>Day 1</h3><p>很早就起床了,看了一眼电脑,然后就出发了。到了 BS 门口,找到了穿着我们学校的校服的同学,然后听到他们在唱生日快乐,找 lym 问了下才知道是 cjg 学长过生日。</p><p>等了一会儿人就进学校了。<del>(某个教练一直让我们在校门口等 zqw 和 tl,结果等不及了进去之后才发现他俩早就进去了。)</del></p><p>我和 lym 巨佬很近,就在斜对面。这是个好兆头!</p><p>开题了,这次密码是 <code>IronHeart</code>,铁胆雄心?<del>那么这次是不是有码量超级大的题啊。</del></p><p>先看题,T1 看着比较简单,T2 不会,T3 不会,T4 看着是道只要肯打就能得分的大膜你。于是决定先做 T1。</p><p>想了一下,这 T1 看着有点像质数筛法啊!于是我准备敲一个类似于欧拉筛的东西,结果发现欧拉筛貌似不行,只好退而求其次,打了个类似于埃氏筛的东西。</p><p>打完了,开开心心按下 F9,然后:</p><p><code>[Error] ld returned 1 exit status</code></p><p>???</p><p>我一脸问号,再编译了几遍,结果是一样的。我觉得是自己的代码出现了问题,于是打了个 A + B,按下 F9,然后:</p><p><code>[Error] ld returned 1 exit status</code></p><p>心 脏 骤 停。</p><p>此时我的心里有一万匹草泥马奔涌而过,于是我举起手<del>召唤</del>找老师……</p><p>老师过来看了很久<del>我的 A + B</del>,调编译参数之类的也没解决,于是他又叫来了另一个老师,这位老师 Dev-C++ 右上角的参数从 <code>TDM-GCC 4.9.2 64-bit Debug</code> 改成了 <code>TDM-GCC 4.9.2 64-bit Release</code>,然后按下 F9:</p><p>电脑上出现了一个黑色的终端,它终于编译起了!</p><p>这个时候那个老师问了我一句:“你会打断点调试吗?”</p><p>我说会。</p><p>他问我要不要换台电脑。</p><p>我看着我的 T1 代码,委婉拒绝了他们好心的建议(我平时几乎不用断点调试)。</p><p>然后他们就走了。</p><p>然后我大概测了下 T1 的代码,大概没问题了,但是样例 4 死活 1.2s 左右怎么都卡不进去。于是先放掉了 T1。</p><p>PS:这人不仅打的玄学复杂度超时,还只打了 $10^7$ 没加一,笑死了。</p><p>T2T3 看上去都没什么思路,于是我吃了一些东西,开始干 T4……的 bfs 暴力。<del>你看看这个人这么逊,肯定只会打最暴力的暴力了 QAQ。</del></p><p>不得不说 T4 码量是真的大,应了那句 <code>IronHeart</code> 啊!我一直在敲,敲了很久很久,最后敲出来还过不了小样例!于是我开始分析,疯狂改 bug <del>造 bug</del>,然后把小样例过了 QWQ。</p><p>代码大概有 5k 吧,这是蒟蒻打过最长的代码了。</p><p>最后还剩半个小时,码了 T2 的暴搜和 T3 的 <code>rand</code>,但是肯定一分都没有……QAQ</p><p><del>话说坐我右边那位大巨佬比赛一开始就开始吃东西,好像是牛肉干,一直吃到了比赛结束,中间从来没断过……</del></p><hr><p>比赛结束几天后自测了一下。</p><p>估分:$90+0+0+rp\approx 90$</p><p>Luogu:$70+0+0+0=70$</p><p>你谷的分出来的时候我心里一紧,写了那么久的 T4 一分都没有吗?心态都要炸了。</p><p>接着 mjl 公布了估计的分数,我 $74$。(什么?我 T4 竟然有分?)</p><p>然后官方公布分数:</p><p>$70+0+0+8=78$</p><p>CCF 少爷姬 NB!</p><p>3= 滚粗了。</p><hr><p>据说 DJ $248$?愣着干啥?赶紧膜拜啊!</p>]]></content>
<summary type="html">炸了炸了,又是 3= QAQ</summary>
<category term="生活" scheme="https://blog.liynw.top/categories/%E7%94%9F%E6%B4%BB/"/>
<category term="游记" scheme="https://blog.liynw.top/tags/%E6%B8%B8%E8%AE%B0/"/>
</entry>
<entry>
<title>P4656 [CEOI2017] Palindromic Partitions 题解</title>
<link href="https://blog.liynw.top/posts/b5735321/"/>
<id>https://blog.liynw.top/posts/b5735321/</id>
<published>2021-12-04T15:35:39.000Z</published>
<updated>2022-02-20T11:45:35.000Z</updated>
<content type="html"><![CDATA[<p>这一定是 ljt 写过的最短的题解。</p><p>先上一个部分分:朴实无华的区间 dp $\text{45pts}$</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstring></span></span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>) <span class="number">1e3</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> T, n, dp[maxn][maxn];</span><br><span class="line"><span class="type">char</span> s[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">bool</span> <span class="title">f</span><span class="params">(<span class="type">int</span> l, <span class="type">int</span> r, <span class="type">int</span> k)</span> </span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i < k; i++) {</span><br><span class="line"> <span class="keyword">if</span>(s[l + i] != s[r + i])</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &T);</span><br><span class="line"> <span class="keyword">while</span>(T--) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%s"</span>, s + <span class="number">1</span>);</span><br><span class="line"> n = <span class="built_in">strlen</span>(s + <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= n; i++)</span><br><span class="line"> dp[i][i] = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> len = <span class="number">2</span>; len <= n; len++) {</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= n - len + <span class="number">1</span>; i++) {</span><br><span class="line"> <span class="type">int</span> j = i + len - <span class="number">1</span>;</span><br><span class="line"> <span class="type">bool</span> flag = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> k = <span class="number">1</span>; k <= len / <span class="number">2</span>; k++) {</span><br><span class="line"> <span class="keyword">if</span>(<span class="built_in">f</span>(i, j - k + <span class="number">1</span>, k)) {</span><br><span class="line"> flag = <span class="number">1</span>;</span><br><span class="line"> dp[i][j] = dp[i + k][j - k] + <span class="number">2</span>;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(!flag)</span><br><span class="line"> dp[i][j] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d\n"</span>, dp[<span class="number">1</span>][n]);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">} </span><br></pre></td></tr></table></figure><hr><p>如上的代码,内存不够,时间也要超限,那我们需要找新的办法。</p><p>正解:贪心 + Hash</p><p>因为要划分为尽量多的部分,所以我们从两边开始找,设两个指针分别指着从左往右数和从右往左数第 $i$ 个字符。只要找到两个字符串一样,就把它们分离出来。</p><p>两个字符串是否一样可以通过 Hash 判断,但是有个问题:我们是从两边往中间枚举的,右边那个字符串是倒着枚举的,怎么判断呢?</p><p>这个很简单,我们只需要判断一下当前右边遍历到的字符是字符串的第几个,假设它是第 $k$ 个,那么就加上它乘以 $base^k$ 即可。</p><p>最后有个细节:如果字符串的长度是奇数,或者还剩下一些字符,那么需要把这些字符作为一个区间,答案要加一。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> ull unsigned long long</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>) <span class="number">1e6</span> + <span class="number">5</span>, p = <span class="number">97</span>, base = <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> T, n;</span><br><span class="line"><span class="type">char</span> s[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &T);</span><br><span class="line"> <span class="keyword">while</span>(T--) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%s"</span>, s + <span class="number">1</span>);</span><br><span class="line"> n = <span class="built_in">strlen</span>(s + <span class="number">1</span>);</span><br><span class="line"> ull hash1 = <span class="number">0ull</span>, hash2 = <span class="number">0ull</span>, pow = <span class="number">1</span>;</span><br><span class="line"> <span class="type">int</span> ans = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= n / <span class="number">2</span>; i++) {</span><br><span class="line"> hash1 = hash1 * p + s[i];</span><br><span class="line"> hash2 = hash2 + s[n - i + <span class="number">1</span>] * pow;</span><br><span class="line"> pow *= p;</span><br><span class="line"> <span class="keyword">if</span>(hash1 == hash2) {</span><br><span class="line"> ans += <span class="number">2</span>;</span><br><span class="line"> hash1 = hash2 = <span class="number">0ull</span>;</span><br><span class="line"> pow = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>((n & <span class="number">1</span>) || hash1)</span><br><span class="line"> ++ans;</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d\n"</span>, ans);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">} </span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">众所周知,CEOI 都是神题。</summary>
<category term="题解" scheme="https://blog.liynw.top/categories/%E9%A2%98%E8%A7%A3/"/>
<category term="贪心" scheme="https://blog.liynw.top/tags/%E8%B4%AA%E5%BF%83/"/>
<category term="哈希" scheme="https://blog.liynw.top/tags/%E5%93%88%E5%B8%8C/"/>
</entry>
<entry>
<title>P6359 [CEOI2018] Cloud computing 题解</title>
<link href="https://blog.liynw.top/posts/b332757/"/>
<id>https://blog.liynw.top/posts/b332757/</id>
<published>2021-12-04T15:27:59.000Z</published>
<updated>2022-01-30T17:14:46.000Z</updated>
<content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p><a href="https://www.luogu.com.cn/problem/P6359">题目链接</a></p><p>我们教练十分努力,竟然找到了这个只有一百多人做的题目。</p><p>这是一道比较有思维难度的 01 背包题,建议评绿或者蓝?</p><hr><h3 id="确定容量和价值"><a href="#确定容量和价值" class="headerlink" title="确定容量和价值"></a>确定容量和价值</h3><p><del>这个输入的变量名很显然就是在提示你把计算机和客户订单混在一起嘛。</del></p><p>我们可以发现,对于每一个计算机,只有<strong>买或不买两种情况</strong>;对于每一个单子,只有<strong>接或不接两种状态。</strong> 而能不能接客户的单子取决于内核的数量够不够。于是,我们想到了这道题的算法——01 背包,内核数量相当于容量,钱相当于价值。</p><p>但是这时就有了一个问题:我怎么确定内核的数量?</p><p>注意到题目中还有另一个条件——时钟频率。因为客户要求有一个对于时钟频率的限制,换句话说,就是<strong>每一个客户能使用的最大内核数量是确定的</strong>。</p><p>所以我们可以把计算机和客户的单子放在一个结构体数组里面,拿一个 <code>bool</code> 区分一下计算机和客户。然后,按照时钟频率排序。</p><p>此时,对于任意一个客户的单子,它<strong>前面的</strong>所有内核数量之和就是对于它来说可以使用的最大内核数。</p><p>这里需要注意一点:如果时钟频率一样,计算机排在前面。如果类型和时钟频率都一样,计算机把价格低的排在前面,客户把价格高的排在前面。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">bool</span> <span class="title">cmp</span><span class="params">(node x, node y)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(x.f != y.f)</span><br><span class="line"> <span class="keyword">return</span> x.f > y.f;</span><br><span class="line"> <span class="keyword">if</span>(x.data != y.data)</span><br><span class="line"> <span class="keyword">return</span> x.data < y.data;</span><br><span class="line"> <span class="keyword">if</span>(!x.data) </span><br><span class="line"> <span class="keyword">return</span> x.v < y.v;</span><br><span class="line"> <span class="keyword">return</span> x.v > y.v;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h3 id="状态转移"><a href="#状态转移" class="headerlink" title="状态转移"></a>状态转移</h3><p>接着就到了比较难的地方。</p><p>设 $dp_{i,j}$ 代表处理了前 $i$ 个请求之后还剩下 $j$ 个可用的内核时能获得的最大利润。</p><p>经上文分析,对于计算机和客户都有两种状态。那么,选择哪种更优呢?</p><p>我们用一个变量 $C$ 来统计<strong>到目前为止</strong>内核的总数量,相当于一个前缀和。然后分析:</p><h4 id="对于计算机"><a href="#对于计算机" class="headerlink" title="对于计算机"></a>对于计算机</h4><p>买的话,需要花钱,但是内核数量会增加。那么相对买之前来说,买后内核数量增加了 $c_i$,也就是说买之前内核数量比现在少 $c_i$,而买后,现在有的钱数量相较于买之前减少了 $v_i$,所以结果表达式如下:</p><script type="math/tex; mode=display">dp_{i-1,j - c_i} - v_i</script><p>至于 $j$ 的循环范围很简单,保证数组下标不超过 $0\sim n$ 的范围即可。</p><p>所以就有对于计算机的状态转移方程:</p><script type="math/tex; mode=display">dp_{i,j}=\max^{C}_{j=c_i}\{dp_{i-1,j-c_i}-v_i\}</script><p>对了,记得在转移之前把前缀和加上。</p><h4 id="对于客户"><a href="#对于客户" class="headerlink" title="对于客户"></a>对于客户</h4><p>接客户的单子,可用的内核数量会减少,但会收获钱。那么接后相对于接前少了 $c_i$ 个内核,但钱增加了 $v_i$,所以结果表达式如下:</p><script type="math/tex; mode=display">dp_{i-1,j+c_i}+v_i</script><p>那状态转移方程就是这样:</p><script type="math/tex; mode=display">dp_{i,j}=\max^{C-c_i}_{j=0}\{dp_{i-1,j+c_i}+v_i\}</script><hr><h3 id="滚动数组"><a href="#滚动数组" class="headerlink" title="滚动数组"></a>滚动数组</h3><p>开二维数组空间不够,于是自然想到了让数组打滚。然而,滚起来之后,$j$ 到底该从小到大还是从大往小?</p><p>这个顺序只取决于一个因素,就是这个状态转移方程<strong>所使用的</strong> $dp$ 值在<strong>需要求的值</strong>的前面还是后面。如果在前面,就需要倒着枚举,如果在后面,就要正着枚举,以保证利用的是本来为 $dp_{i-1,?}$ 而非 $dp_{i,?}$。</p><p>所以,处理购买计算机的请求要从大到小枚举,处理客户单子需要从小到大枚举。</p><p>注意一下初始值,数组赋极小值,$dp_{0}=0$。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= num; i++) {</span><br><span class="line"> <span class="keyword">if</span>(!a[i].data) { <span class="comment">// 计算机 </span></span><br><span class="line"> C += a[i].c;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> j = C; j >= a[i].c; j--)</span><br><span class="line"> dp[j] = std :: <span class="built_in">max</span>(dp[j], dp[j - a[i].c] - a[i].v);</span><br><span class="line"> } <span class="keyword">else</span> { <span class="comment">// 客户 </span></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">0</span>; j <= C - a[i].c; j++) </span><br><span class="line"> dp[j] = std :: <span class="built_in">max</span>(dp[j], dp[j + a[i].c] + a[i].v);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h3 id="求答案"><a href="#求答案" class="headerlink" title="求答案"></a>求答案</h3><p>非常简单,长这样:</p><script type="math/tex; mode=display">ans=\max_{i=0}^{C}\{dp_i\}</script><p>注意,$i$ 的初始值为 $0$。</p><p>我最开始做的时候以为这个地方初始值是 $1$,因为 $ans$ 初始值就是 $0$ 嘛!于是喜提 $\text{18pts}$……</p><p>其实最终 $dp_0$ 不一定是没有购买计算机,也有可能是<strong>内核数量刚好消耗完</strong>。</p><p><del>Peter:这其实就和牛顿第一定律一样嘛,要么不受外力,要么合力为零,两种情况嘛。</del></p><p><del>我承认你说得很有道理,但是你是物理学疯了?</del></p><hr><h3 id="Code"><a href="#Code" class="headerlink" title="Code"></a>Code</h3><p>不开 <code>long long</code> 见祖宗。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><algorithm></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> int long long</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>) <span class="number">2e5</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">node</span> { <span class="type">int</span> c, f, v; <span class="type">bool</span> data; } a[<span class="number">4005</span>];</span><br><span class="line"><span class="type">int</span> C, n, m, num, ans, dp[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">cmp</span><span class="params">(node x, node y)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(x.f != y.f)</span><br><span class="line"> <span class="keyword">return</span> x.f > y.f;</span><br><span class="line"> <span class="keyword">if</span>(x.data != y.data)</span><br><span class="line"> <span class="keyword">return</span> x.data < y.data;</span><br><span class="line"> <span class="keyword">if</span>(!x.data) </span><br><span class="line"> <span class="keyword">return</span> x.v < y.v;</span><br><span class="line"> <span class="keyword">return</span> x.v > y.v;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">signed</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">memset</span>(dp, <span class="number">-0x3f</span>, <span class="built_in">sizeof</span>(dp));</span><br><span class="line"> dp[<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%lld"</span>, &n);</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%lld %lld %lld"</span>, &a[i].c, &a[i].f, &a[i].v);</span><br><span class="line"> a[i].data = <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%lld"</span>, &m);</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = n + <span class="number">1</span>; i <= n + m; i++) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%lld %lld %lld"</span>, &a[i].c, &a[i].f, &a[i].v);</span><br><span class="line"> a[i].data = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> num = m + n;</span><br><span class="line"> std :: <span class="built_in">stable_sort</span>(a + <span class="number">1</span>, a + num + <span class="number">1</span>, cmp);</span><br><span class="line"> <span class="comment">/*</span></span><br><span class="line"><span class="comment"> for(int i = 1; i <= num; i++) </span></span><br><span class="line"><span class="comment"> printf("%d %d %d %d\n", a[i].c, a[i].f, a[i].v, a[i].data);</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= num; i++) {</span><br><span class="line"> <span class="keyword">if</span>(!a[i].data) { <span class="comment">// 计算机 </span></span><br><span class="line"> C += a[i].c;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> j = C; j >= a[i].c; j--)</span><br><span class="line"> dp[j] = std :: <span class="built_in">max</span>(dp[j], dp[j - a[i].c] - a[i].v);</span><br><span class="line"> } <span class="keyword">else</span> { <span class="comment">// 客户 </span></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">0</span>; j <= C - a[i].c; j++) </span><br><span class="line"> dp[j] = std :: <span class="built_in">max</span>(dp[j], dp[j + a[i].c] + a[i].v);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i <= C; i++)</span><br><span class="line"> ans = std :: <span class="built_in">max</span>(ans, dp[i]);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%lld"</span>, ans);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><a href="https://www.luogu.com.cn/record/62378782">AC 记录</a></p>]]></content>
<summary type="html">茫茫云海中的题目~</summary>
<category term="题解" scheme="https://blog.liynw.top/categories/%E9%A2%98%E8%A7%A3/"/>
<category term="动态规划" scheme="https://blog.liynw.top/tags/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/"/>
</entry>
<entry>
<title>CSP2021 游记</title>
<link href="https://blog.liynw.top/posts/9ec8265c/"/>
<id>https://blog.liynw.top/posts/9ec8265c/</id>
<published>2021-11-07T10:55:12.000Z</published>
<updated>2022-02-20T11:45:35.000Z</updated>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>初二 CQ OIer,去年卡线省一(不会 <code>sort</code> 捞了 $\text{15pts}$),今年 CSP 划水。</p><p>感觉要退役了 qwq。</p><p>至于去年为啥没游记,我去年都不知道什么是游记……</p><hr><h2 id="初赛篇"><a href="#初赛篇" class="headerlink" title="初赛篇"></a>初赛篇</h2><h3 id="Day"><a href="#Day" class="headerlink" title="Day ???"></a>Day ???</h3><p><del>我去 TG 不就是去划水的吗。</del></p><p>因为双减似乎课没法上了,于是搞 OI 的时间变成了每天中午的中午训练。</p><p>mjl 真好玩,一天(一个小时)布置的任务如下:</p><ul><li><p>某年的 PJ <strong>和</strong> TG 初赛卷子</p></li><li><p>一道题(难度绿及以上)</p></li></ul><p>【我看不懂,但我大受震撼 orz】.jpg</p><p>放弃了 c++ 的题目,去搞初赛了。</p><hr><h3 id="Day-0"><a href="#Day-0" class="headerlink" title="Day 0"></a>Day 0</h3><p>中午发了准考证。</p><p>然而,我突然发现我们学校为了省墨用的是黑白。</p><p>本来也没啥的,但是大家都知道,准考证上有本人照片……</p><p>于是机房就【数据删除】了(</p><p>看了下准考证号,PJ 600多,TG 200多。</p><hr><p>下楼的时候。</p><p>Peter:我觉得这次大题选 A 的几率特别高!(<code>flag</code>)</p><hr><h3 id="Day-1"><a href="#Day-1" class="headerlink" title="Day 1"></a>Day 1</h3><p>本来说的是 7:30 起床,结果 7:00 就醒了。吃早饭之后发了个 <code>rp++</code>,就去考前颓废了(</p><p>提前半个小时到了我们学校高中部(考点),看了安排表,发现我们学校的大巨佬都在这儿了(甚至还有两个来拉高过关线的高三 NOI 金牌大佬),小蒟蒻十分紧张/kel。</p><p>初一初二一群人在科技楼一楼打打闹闹了至少 15 分钟,<del>期间我们甚至欣赏到了 XSC062 的可爱萝莉音(大雾)</del>。</p><p>然后社长<del>(cháng)</del>说他看到有人去 6 楼了,于是我们一行人坐电梯到六楼看到了 mjl……</p><h4 id="上午-TG"><a href="#上午-TG" class="headerlink" title="上午-TG"></a>上午-TG</h4><p>emm 我忘带身份证了?mjl 说穿着校服就行。哦那没事了。</p><p>9:30 开始考试,第一题是个啥?</p><p>继续做题,后面的题(指选择题)还好,不是很毒瘤。</p><p>开始做程序阅读。好家伙第一题就来立体几何?出题人我谢谢您。</p><blockquote><p>对了,话说 <code>acos(0.5)</code> 是什么啊?</p><p>Update:问了数学竞赛的同学,原来是反三角函数,当时我连这个数的近似值都不知道,肯定没办法手动模拟。</p></blockquote><p>第二题看上去是一个莫名其妙的求区间最大值,那个 Node 看了我好久,不过最终还是看明白了(大概吧?),希望不要出锅(小声 bb)。</p><p>第三题……好家伙直接手算 <code>base64</code>。出题人我谢谢您。</p><p>做完程序阅读只剩下了 20 分钟,有点慌。</p><p>开<del>完形填空</del>完善程序!</p><p>第一题乍一看是个数学题,再一看是个模拟题,因为时间不够了就大概看了下,随便口胡了几个上去。(T4 我故意选了个带 $r$ 的,然后就没了)</p><blockquote><p>我有个 $r$,诶,我不用,就是玩儿~</p></blockquote><p>出题人我谢谢您。</p><p>五分钟搞完第一题,开第二题。</p><p>第一眼:我看到了一个 <code>001</code>?感觉不妙。<del>去年 90 多行的手动模拟队列已经够了吧。</del></p><p>第二眼:RMQ??<del>又是什么奇奇怪怪的数据结构。</del> 等等,现学??出题人我谢谢您。</p><p>此时我又想起了昨天 Peter 的 <code>flag</code>。</p><p>于是我写了 6 个 A 上去。我倒是要看看他押题的能力怎么样(</p><p>于是 TG 就这么裂开了。</p><p>中午在机房看了民间答案之后的估分:$39.5$</p><hr><p>从考场出来之后,某个人因为太饿了,于是随手拔起一根草塞进了嘴里……</p><p>XSC062:这啥啊,怎么是酸的?</p><p>我:草(真·一种植物)。</p><p>和 Peter 还有 XSC062 聊了一下,发现我选择 T1 做错了(我不知道为什么我选成了 <code>cd</code>,答案应该是 <code>ls</code>),还了解到最后一道大题 D 最多。</p><p>我觉得我药丸了。</p><hr><h4 id="下午-PJ"><a href="#下午-PJ" class="headerlink" title="下午-PJ"></a>下午-PJ</h4><p>选择原题一堆,程序阅读继续手算 <code>base64</code>(</p><p>阅读 T2 好像是个奇奇怪怪的欧拉筛,不过那四个数组是啥没看懂 qwq。<del>像极了我平时敲代码乱取变量名的样子。</del></p><p><del>出题人,我错了,我以后再也不乱取变量名了!能不能饶了我!</del></p><p>其余不做评价……</p><p>估分:$62.5$</p><hr><h3 id="Day-n"><a href="#Day-n" class="headerlink" title="Day n"></a>Day n</h3><blockquote><p>指 9.27。</p></blockquote><p>出分了!</p><p>PJ:$72.5$</p><p>TG:$47$</p><p>TG 卡线过了,喜大普奔(</p><hr><h2 id="复赛篇"><a href="#复赛篇" class="headerlink" title="复赛篇"></a>复赛篇</h2><h3 id="Day-?"><a href="#Day-?" class="headerlink" title="Day ?"></a>Day ?</h3><p>因为我去年已经卡线 PJ1= 了,所以我妈没给我报 PJ,只报了 TG。</p><p>所以要求别那么高吧,我只是想要个 2= + 六级蓝勾勾 qwq。</p><hr><h3 id="Day-1-1"><a href="#Day-1-1" class="headerlink" title="Day 1"></a>Day 1</h3><p>上午补初赛游记,复习了下图论和高精的板子 <del>(然后根本没用上)</del>。</p><p>$\text{CSP 2021 rp++!}$</p><hr><p>下午到的比较早,找了了 xzj 和 zm<del>一起膜拜高年级的大佬</del>。其他人因为参加了普及还在学校里面的。</p><p>等了一会儿进去了,然后又是<del>互相膜拜,膜拜初三高中的巨佬</del>和奶题(zm:这次肯定有数据结构!),和初一初二的同学会合,然后进行传统艺能——照<del>遗</del>合照。</p><p>话说 BS 为什么不发三明治啊!去年 NK 都发了!!</p><p>到了机房,按照老师说的,新建文件,关机重启,下载 C++ 编译器,打框架。</p><p>然后密码发下来了。<del>什么鬼怎么是乱码,CCF 您可以用心一点吗。</del></p><p>打开题,通览一遍,直接确认 T4 是到不可做题。然后大概看了下,T1 是最简单的(Update:其实应该是 T3,但是当时没想到 T3 比 T1 简单,结果把 T1 的近似正解硬刚出来了),于是开始想 T1。</p><p>不过我想了很久,都只能想到 $O(n^2)$。然后突然想到可以用优先队列,貌似可以优化时间复杂度 <del>(虽然最后做出来还是两层循环……)</del></p><p>做了很久,中途突然发现做法假了样例过不了,后来才回忆起有结构体这回事……</p><p>差点忘了运算符重载……幸好想起来了。(<code>flag</code>)</p><p>时间复杂度 $O(n\log n)$,估分 $100\text{pts}$ 吧。</p><p>去上了个厕所,喝了点水,但是 T2T3 还是没思路。</p><p>然后我发现 T2 虽然感觉在哪里看到过但就是十分令人自闭(我的区间 DP 烂到不行),于是开始敲 T3 $O(2^{2n})$ 暴搜。这个暴搜很简单,一会儿就敲完了。</p><p>估分 $\text{28pts}$。</p><p>最后看了看 T2,因为想不出来十分自闭决定打全排列暴搜,结果暴搜都差点没打出来……因为不会判断字符串是否合法。</p><p>幸好最后 $10$ 分钟过样例了 qwq。</p><p>估分 $\text{15pts}$。</p><hr><p>出来之后又和 Peter 和 XSC062 聊(别问我为啥总是他们俩),得知基本上和我一样打暴搜,内心逐渐趋于平静……</p><hr><h3 id="Day-2"><a href="#Day-2" class="headerlink" title="Day 2"></a>Day 2</h3><p>洛谷民间数据冲鸭!</p><p>结果出事了。</p><p>详情请见这个<a href="https://www.luogu.com.cn/discuss/371587">帖子</a>。</p><details class="folding-tag" blue><summary> 点击查看 CE 事件具体过程 </summary> <div class='content'> <p>帖子说得可能不太清楚……</p><p>我在考场上敲 T1 的时候忘了运算符重载怎么写,于是想了很久把 <code>operator</code> 这个单词想起来了,于是就敲了一句:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">operator</span><(<span class="type">const</span> node x, <span class="type">const</span> node y) { <span class="keyword">return</span> x.Time > y.Time; }</span><br></pre></td></tr></table></figure><p>结果就少敲了前面的一个 <code>bool</code>,也就是说,正确的写法应该是这样的:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">bool</span> <span class="keyword">operator</span><(<span class="type">const</span> node x, <span class="type">const</span> node y) { <span class="keyword">return</span> x.Time > y.Time; }</span><br></pre></td></tr></table></figure><p>好玩的是,CQ 没有提供 Linux 虚拟机,只提供了 Win7 的系统,然后这玩意儿正好在 Windows 系统可以过编译,然后在 Linux 上 CE 了……</p><p>更好玩的是,DJ 大佬在参加 PJ 的时候,T3 和我犯了一模一样的错误,和我一样挂了 $100$ 分,如果我们两个不挂这两道题的话,他就 AK 比赛了,我就有 7 级蓝勾了。</p><p>只可惜这个世界上没有什么如果。</p> </div> </details><p>我太 TM 高兴了,直接从 $143$ 挂到了 $43$,但凡我 T1 打个 $40$ 分的暴力也不至于这样。</p><hr><h3 id="Day-3"><a href="#Day-3" class="headerlink" title="Day 3"></a>Day 3</h3><p>向 mjl 吐槽 CCF 的测评环境问题导致我挂 100 分,他说没办法申诉。</p><p>然后因为是 Dev-C++ 的环境问题嘛,CQ 目测这几年还没办法搞 Linux 系统,所以 mjl 帮我测了一下 CodeBlocks,结果那个上面也能过。</p><p>所以这种问题只能依靠自己的力量了吗……</p><p>希望 CQ 明年可以有 NOI Linux 2.0 的虚拟机 QWQ。</p><hr><h3 id="Day-7"><a href="#Day-7" class="headerlink" title="Day 7"></a>Day 7</h3><p>过去了一周,mjl 叫我们补前三题。</p><p><em>(๑•̀ㅂ•́)و✧夹带私货:</em><a href="/posts/b7fede58/"><em>CSP-S2021 T1 题解</em></a></p><p>然后晚上出分了。</p><p><img src="https://cdn.luogu.com.cn/upload/image_hosting/lut2vgpp.png" alt=""></p><p>和预估一样。</p><hr><h3 id="Day-n-1"><a href="#Day-n-1" class="headerlink" title="Day n"></a>Day n</h3><blockquote><p>指出结果的那一天。</p></blockquote><p>结果还算好,没打铁,得了个 3=。</p><p>还好还好有奖,就是不知道 NOIP 审核给不给过 QwQ……</p>]]></content>
<summary type="html">关于某个** ljt 是怎么把到手的 S 组 1= 和 7 级蓝勾搞没的</summary>
<category term="生活" scheme="https://blog.liynw.top/categories/%E7%94%9F%E6%B4%BB/"/>
<category term="游记" scheme="https://blog.liynw.top/tags/%E6%B8%B8%E8%AE%B0/"/>
</entry>
<entry>
<title>「CSP-S 2021」廊桥分配 题解</title>
<link href="https://blog.liynw.top/posts/b7fede58/"/>
<id>https://blog.liynw.top/posts/b7fede58/</id>
<published>2021-11-07T10:28:46.000Z</published>
<updated>2022-01-30T17:42:57.000Z</updated>
<content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>如果您是从 ljt 的 CSP 游记过来的,那么您应该已经知道了 CE 惨案。如果您和我一样有这一类问题的话可以访问<a href="https://loj.ac/d/3422">这个帖子</a>,上面有一些值得采纳的建议。</p><hr><h3 id="题解"><a href="#题解" class="headerlink" title="题解"></a>题解</h3><p>设 $s1_i$ 为国内航班有 $i$ 个停机位时能停在停机位的<strong>新增加</strong>的飞机个数。$s2_i$ 为国际,同理。</p><p>那么,我们需要一个结构体的优先队列来存每一个停机位的信息:会被占用到多久,停机位的编号。按照被占用截止时间从小到大排序。</p><p>而且,优先队列里只能存此时被占用的停机位。</p><hr><h3 id="具体实现"><a href="#具体实现" class="headerlink" title="具体实现"></a>具体实现</h3><p><strong>国内和国际分开枚举。</strong></p><p>拿一个 <code>bool</code> 数组 $is\_zhan$,$is\_zhan_i$ 代表第 $i$ 个停机位是否被占用。</p><p>每一次有一个飞机来的时候,就先把所被有占用截止时间小于这个飞机到达时间的停机位全部弹掉,然后从 $1$ 号机位开始统计,直到枚举到一个没有被占用的机位 $j$,就意味着这个飞机在机位数量至少为 $j$ 的时候可以停在停机坪上,所以:$s1_i ← s1_i + 1$。</p><p>国际同理。</p><p>最后再统计 $s1$ 和 $s2$ 的前缀和,枚举分配 $0\sim n$ 个机位给国内,找最大值。</p><p>时间复杂度 $O(M\log n + rp)$。(第二层循环不知道会卡多久)</p><hr><h3 id="正确性证明"><a href="#正确性证明" class="headerlink" title="正确性证明"></a>正确性证明</h3><p>cgy 大佬说我没有正确性证明,那我就来补一个吧。(不过这个东西感觉有点只可意会不可言传,可能我说得不清楚,见谅。)</p><p>我们打的优先队列在<strong>假设一种情况</strong>:有 $m$ 个停机位,从左到右编号为 $1, 2, \ldots, m$。这样可以保证所有飞机都能停到停机位里。</p><p>每一次有一个飞机到达的时候,我们就选择最左边的那个机位停飞机。此时,这个机位的编号就是它能停到停机位里所需要的最少的停机位数量。</p><p>为什么呢?</p><p>因为每一个飞机都在尽量往左边停,如果它停在了右边,就说明<strong>它来的时候左边的所有机位都被占领了,它只能停在右边。</strong> 我们假设它停在 $j$ 号位,刚才说的那个飞机停在 $i$ 号位,那么,对于任意一个停机位数量 $i\le k < j$,都满足 $i$ 飞机可以停,但 $j$ 飞机不可以停的情况。</p><p>它右边的所有飞机都满足这个条件,而它左边的飞机都可以把它当做右边的飞机满足这个条件。所以 $i$ 飞机可以停的条件为 $i\le k$,而我们需要<strong>在可以停相同数量的飞机时,尽量节约停机位数量,使得另一个区域的飞机能停更多</strong>,所以上述条件成立。</p><hr><h3 id="注意"><a href="#注意" class="headerlink" title="注意"></a>注意</h3><p>需要把国内和国际的飞机按照<strong>到达时间</strong>排序。</p><hr><h3 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><bits/stdc++.h></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>) <span class="number">1e5</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">node</span> { <span class="type">int</span> s, t; } a[maxn], b[maxn];</span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">que</span> { <span class="type">int</span> Time, num; };</span><br><span class="line"><span class="type">int</span> n, tot, m1, m2, ans, s1[maxn], s2[maxn], sum1[maxn], sum2[maxn];</span><br><span class="line"><span class="type">bool</span> is_zhan[maxn];</span><br><span class="line">priority_queue <que> q;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">cmp</span><span class="params">(node x, node y)</span> </span>{ <span class="keyword">return</span> x.s < y.s; }</span><br><span class="line"><span class="type">bool</span> <span class="keyword">operator</span><(<span class="type">const</span> que x, <span class="type">const</span> que y) { <span class="keyword">return</span> x.Time > y.Time; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="comment">//freopen("airport.in", "r", stdin);</span></span><br><span class="line"> <span class="comment">//freopen("airport.out", "w", stdout);</span></span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d %d"</span>, &n, &m1, &m2);</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= m1; i++) <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &a[i].s, &a[i].t);</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= m2; i++) <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &b[i].s, &b[i].t);</span><br><span class="line"> <span class="built_in">stable_sort</span>(a + <span class="number">1</span>, a + m1 + <span class="number">1</span>, cmp);</span><br><span class="line"> <span class="built_in">stable_sort</span>(b + <span class="number">1</span>, b + m2 + <span class="number">1</span>, cmp);</span><br><span class="line"> <span class="comment">//国内</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= m1; i++) {</span><br><span class="line"> <span class="keyword">while</span>(!q.<span class="built_in">empty</span>() && q.<span class="built_in">top</span>().Time < a[i].s) {</span><br><span class="line"> is_zhan[q.<span class="built_in">top</span>().num] = <span class="number">0</span>;</span><br><span class="line"> q.<span class="built_in">pop</span>();</span><br><span class="line"> }</span><br><span class="line"> tot = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span>(is_zhan[tot]) ++tot;</span><br><span class="line"> is_zhan[tot] = <span class="number">1</span>;</span><br><span class="line"> ++s1[tot];</span><br><span class="line"> que qwq;</span><br><span class="line"> qwq.Time = a[i].t;</span><br><span class="line"> qwq.num = tot;</span><br><span class="line"> q.<span class="built_in">push</span>(qwq);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">memset</span>(is_zhan, <span class="number">0</span>,<span class="built_in">sizeof</span>(is_zhan));</span><br><span class="line"> <span class="keyword">while</span>(!q.<span class="built_in">empty</span>()) q.<span class="built_in">pop</span>();</span><br><span class="line"> <span class="comment">//国际 </span></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= m2; i++) {</span><br><span class="line"> <span class="keyword">while</span>(!q.<span class="built_in">empty</span>() && q.<span class="built_in">top</span>().Time < b[i].s) {</span><br><span class="line"> is_zhan[q.<span class="built_in">top</span>().num] = <span class="number">0</span>;</span><br><span class="line"> q.<span class="built_in">pop</span>();</span><br><span class="line"> }</span><br><span class="line"> tot = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span>(is_zhan[tot]) ++tot;</span><br><span class="line"> is_zhan[tot] = <span class="number">1</span>;</span><br><span class="line"> ++s2[tot];</span><br><span class="line"> que qwq;</span><br><span class="line"> qwq.Time = b[i].t;</span><br><span class="line"> qwq.num = tot;</span><br><span class="line"> q.<span class="built_in">push</span>(qwq);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//汇总 </span></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= n; i++) sum1[i] = sum1[i - <span class="number">1</span>] + s1[i];</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= n; i++) sum2[i] = sum2[i - <span class="number">1</span>] + s2[i];</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i <= n; i++) ans = <span class="built_in">max</span>(ans, sum1[i] + sum2[n - i]);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d"</span>, ans);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h3 id="优化"><a href="#优化" class="headerlink" title="优化"></a>优化</h3><p>这个代码在洛谷和官方吸氧能过,但是我们 OJ 自造的毒瘤数据过不了(<del>而且教练死活不开 O2</del>)所以就有了优化。</p><p>大家注意到上面代码的一句:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">while</span>(is_zhan[tot]) ++tot;</span><br></pre></td></tr></table></figure><p>这玩意儿要是数据毒瘤能把时间复杂度卡到 $O(Mn\log n)$。</p><p>于是我们可以再开一个优先队列存没有被占用的机位,按照编号从小到大排序,每次只需要从这个序列里取第一个就行了。</p><p>所以 $is\_zhan$ 数组就这么退役了 qwq。</p><p>时间复杂度 $O(M\log n)$,跑得飞快。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><bits/stdc++.h></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">pragma</span> G++ optimize(2)</span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>) <span class="number">1e5</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">node</span> { <span class="type">int</span> s, t; } a[maxn], b[maxn];</span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">que</span> { <span class="type">int</span> Time, num; };</span><br><span class="line"><span class="type">int</span> n, tot, m1, m2, ans, s1[maxn], s2[maxn], sum1[maxn], sum2[maxn];</span><br><span class="line">priority_queue <que> q;</span><br><span class="line">priority_queue <<span class="type">int</span>, vector <<span class="type">int</span>>, greater <<span class="type">int</span>> > no_zhan;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">cmp</span><span class="params">(node x, node y)</span> </span>{ <span class="keyword">return</span> x.s < y.s; }</span><br><span class="line"><span class="type">bool</span> <span class="keyword">operator</span> < (<span class="type">const</span> que x, <span class="type">const</span> que y) { <span class="keyword">return</span> x.Time > y.Time; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d %d"</span>, &n, &m1, &m2);</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= m1; i++) <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &a[i].s, &a[i].t);</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= m2; i++) <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &b[i].s, &b[i].t);</span><br><span class="line"> <span class="built_in">stable_sort</span>(a + <span class="number">1</span>, a + m1 + <span class="number">1</span>, cmp);</span><br><span class="line"> <span class="built_in">stable_sort</span>(b + <span class="number">1</span>, b + m2 + <span class="number">1</span>, cmp);</span><br><span class="line"> <span class="comment">//国内</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= m1; i++) no_zhan.<span class="built_in">push</span>(i);</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= m1; i++) {</span><br><span class="line"> <span class="keyword">while</span>(!q.<span class="built_in">empty</span>() && q.<span class="built_in">top</span>().Time < a[i].s) {</span><br><span class="line"> no_zhan.<span class="built_in">push</span>(q.<span class="built_in">top</span>().num);</span><br><span class="line"> q.<span class="built_in">pop</span>();</span><br><span class="line"> }</span><br><span class="line"> tot = no_zhan.<span class="built_in">top</span>();</span><br><span class="line"> no_zhan.<span class="built_in">pop</span>();</span><br><span class="line"> ++s1[tot];</span><br><span class="line"> que qwq;</span><br><span class="line"> qwq.Time = a[i].t;</span><br><span class="line"> qwq.num = tot;</span><br><span class="line"> q.<span class="built_in">push</span>(qwq);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">while</span>(!q.<span class="built_in">empty</span>()) q.<span class="built_in">pop</span>();</span><br><span class="line"> <span class="keyword">while</span>(!no_zhan.<span class="built_in">empty</span>()) no_zhan.<span class="built_in">pop</span>();</span><br><span class="line"> <span class="comment">//国际 </span></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= m2; i++) no_zhan.<span class="built_in">push</span>(i);</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= m2; i++) {</span><br><span class="line"> <span class="keyword">while</span>(!q.<span class="built_in">empty</span>() && q.<span class="built_in">top</span>().Time < b[i].s) {</span><br><span class="line"> no_zhan.<span class="built_in">push</span>(q.<span class="built_in">top</span>().num);</span><br><span class="line"> q.<span class="built_in">pop</span>();</span><br><span class="line"> }</span><br><span class="line"> tot = no_zhan.<span class="built_in">top</span>();</span><br><span class="line"> no_zhan.<span class="built_in">pop</span>();</span><br><span class="line"> ++s2[tot];</span><br><span class="line"> que qwq;</span><br><span class="line"> qwq.Time = b[i].t;</span><br><span class="line"> qwq.num = tot;</span><br><span class="line"> q.<span class="built_in">push</span>(qwq);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//汇总 </span></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= n; i++) sum1[i] = sum1[i - <span class="number">1</span>] + s1[i];</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= n; i++) sum2[i] = sum2[i - <span class="number">1</span>] + s2[i];</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i <= n; i++) ans = <span class="built_in">max</span>(ans, sum1[i] + sum2[n - i]);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d"</span>, ans);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">考场上挂了嘤嘤嘤</summary>
<category term="题解" scheme="https://blog.liynw.top/categories/%E9%A2%98%E8%A7%A3/"/>
<category term="STL" scheme="https://blog.liynw.top/tags/STL/"/>
</entry>
<entry>
<title>2021.10.16 考试总结</title>
<link href="https://blog.liynw.top/posts/ad60f6f3/"/>
<id>https://blog.liynw.top/posts/ad60f6f3/</id>
<published>2021-10-17T23:12:08.000Z</published>
<updated>2022-02-20T11:45:35.000Z</updated>
<content type="html"><![CDATA[<p>总分 $500$,得分 $90$。非常裂开,非常无语(ˉ▽ˉ;)…</p><p>欢迎收看《关于 ljt 是怎么挂掉 $\text{240pts}$ 的》。</p><hr><h3 id="T1"><a href="#T1" class="headerlink" title="T1"></a>T1</h3><p>一道很简单的贪心,把运动员按照能力大小排序,统计运动员的总参赛时间,如果没到就加上这个运动员的能力值与参加比赛时间之积。另外,因为我们是按照能力值从大到小排序的,所以需要让排在前面的运动员尽量多一些时间,<del>也就是说,这道题里面我们要当万恶的资本家,把能力值最大的几个运动员都榨干</del>。</p><p>不开 <code>long long</code> 见祖宗,挂了 $\text{40pts}$。另外一定要注意 <code>long long</code> 要开全,否则会导致 $\text{65pts}$ 惨案。</p><p><del>zszz,<code>#define int long long</code> 是个好东西</del>。</p><p>代码:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><algorithm></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> int long long</span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = <span class="number">505</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">node</span> { <span class="type">int</span> k, l; } a[maxn];</span><br><span class="line"><span class="type">int</span> m, n, tot, ans;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">cmp</span><span class="params">(node x, node y)</span> </span>{ <span class="keyword">return</span> x.k > y.k; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">signed</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">freopen</span>(<span class="string">"marathon.in"</span>, <span class="string">"r"</span>, stdin);</span><br><span class="line"> <span class="built_in">freopen</span>(<span class="string">"marathon.out"</span>, <span class="string">"w"</span>, stdout);</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%lld %lld"</span>, &m, &n);</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= n; i++) <span class="built_in">scanf</span>(<span class="string">"%lld %lld"</span>, &a[i].k, &a[i].l);</span><br><span class="line"> <span class="built_in">stable_sort</span>(a + <span class="number">1</span>, a + n + <span class="number">1</span>, cmp);</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="keyword">if</span>(tot >= <span class="number">6</span> * m) <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(tot + a[i].l <= <span class="number">6</span> * m) {</span><br><span class="line"> ans += a[i].k * a[i].l;</span><br><span class="line"> tot += a[i].l;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> ans += a[i].k * (<span class="number">6</span> * m - tot);</span><br><span class="line"> tot = <span class="number">6</span> * m;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%lld"</span>, ans);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">} </span><br></pre></td></tr></table></figure><p><del>说句闲话:对了,你们有没有注意到 ljt 最近换码风了?我感觉之前那种太紧凑了不好调代码就换了 qwq。</del></p><hr><h3 id="T2"><a href="#T2" class="headerlink" title="T2"></a>T2</h3><p>《关于 ljt 因为把 <code>Friday</code> 打成 <code>Firday</code> 而痛失 $\text{100pts}$ 这回事》</p><p>直接无语了。</p><p>小模拟,<del>觉得这道题不过瘾的可以去做做儒略日</del>,注意闰年的判断,以及初始值($2011.1.1$ 是星期六)。</p><ol><li>普通年能被 $4$ 整除且不能被 $100$ 整除的为闰年。(如 $2004$ 年就是闰年,$1901$ 年不是闰年)</li><li>世纪年能被 $400$ 整除的是闰年。(如 $2000$ 年是闰年,$1900$ 年不是闰年)</li></ol><p>因为数据很大,而且是多组数据(考试范围写的是时间早于 $99999.12.31$ 后来数据只出到了 $3199.12.31$……离谱),我们可以使用一个办法来避免 TLE ——<strong>离线</strong>。</p><p>离线大概就是<strong>一次性把所有测试数据都存下来</strong>,按照大小排序,这样只用跑一遍从 $2011$ 到 $99999$ 的年份就可以判断完所有数据。</p><p>具体看代码:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><algorithm></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 2011/01/01: Saturday</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn =(<span class="type">int</span>)<span class="number">1e5</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">node</span> { <span class="type">int</span> y, m, d, num, ans; } a[<span class="number">105</span>];</span><br><span class="line"><span class="type">int</span> M[<span class="number">2</span>][<span class="number">13</span>] = { {<span class="number">0</span>, <span class="number">31</span>, <span class="number">28</span>, <span class="number">31</span>, <span class="number">30</span>, <span class="number">31</span>, <span class="number">30</span>, <span class="number">31</span>, <span class="number">31</span>, <span class="number">30</span>, <span class="number">31</span>, <span class="number">30</span>, <span class="number">31</span>}, {<span class="number">0</span>, <span class="number">31</span>, <span class="number">29</span>, <span class="number">31</span>, <span class="number">30</span>, <span class="number">31</span>, <span class="number">30</span>, <span class="number">31</span>, <span class="number">31</span>, <span class="number">30</span>, <span class="number">31</span>, <span class="number">30</span>, <span class="number">31</span>} };</span><br><span class="line"><span class="type">int</span> date = <span class="number">6</span>;</span><br><span class="line"><span class="comment">// sunday,monday,tuesday,wednesday,thursday,friday,saturday</span></span><br><span class="line"><span class="type">char</span> ans[<span class="number">7</span>][<span class="number">15</span>] = { <span class="string">"Sunday"</span>, <span class="string">"Monday"</span>, <span class="string">"Tuesday"</span>, <span class="string">"Wednesday"</span>, <span class="string">"Thursday"</span>, <span class="string">"Friday"</span>, <span class="string">"Saturday"</span> };</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">earlier</span><span class="params">(<span class="type">int</span> y1, <span class="type">int</span> m1, <span class="type">int</span> d1, <span class="type">int</span> y2, <span class="type">int</span> m2, <span class="type">int</span> d2)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(y1 < y2) <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(y1 > y2) <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">if</span>(m1 < m2) <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(m1 > m2) <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">if</span>(d1 < d2) <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">cmp1</span><span class="params">(node x, node y)</span> </span>{ <span class="keyword">return</span> <span class="built_in">earlier</span>(x.y, x.m, x.d, y.y, y.m, y.d); }</span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">cmp2</span><span class="params">(node x, node y)</span> </span>{ <span class="keyword">return</span> x.num < y.num; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">run</span><span class="params">(<span class="type">int</span> y)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(y % <span class="number">4</span>) <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(y % <span class="number">100</span>) <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(!(y % <span class="number">400</span>)) <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">freopen</span>(<span class="string">"date.in"</span>, <span class="string">"r"</span>, stdin);</span><br><span class="line"> <span class="built_in">freopen</span>(<span class="string">"date.out"</span>, <span class="string">"w"</span>, stdout);</span><br><span class="line"> <span class="type">int</span> tot = <span class="number">1</span>, Num = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span>(<span class="built_in">scanf</span>(<span class="string">"%d %d %d"</span>, &a[tot].y, &a[tot].m, &a[tot].d) != EOF) {</span><br><span class="line"> a[tot].num = tot;</span><br><span class="line"> ++tot;</span><br><span class="line"> }</span><br><span class="line"> --tot;</span><br><span class="line"> <span class="built_in">stable_sort</span>(a + <span class="number">1</span>, a + tot + <span class="number">1</span>, cmp1);</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> year = <span class="number">2011</span>; year <= a[tot].y; year++) {</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> month = <span class="number">1</span>; month <= <span class="number">12</span>; month++) {</span><br><span class="line"> <span class="type">int</span> t = <span class="built_in">run</span>(year) ? <span class="number">1</span> : <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> day = <span class="number">1</span>; day <= M[t][month]; day++) {</span><br><span class="line"> <span class="keyword">while</span>(year == a[Num].y && month == a[Num].m && day == a[Num].d) {</span><br><span class="line"> a[Num].ans = date;</span><br><span class="line"> ++Num;</span><br><span class="line"> }</span><br><span class="line"> date = (date + <span class="number">1</span>) % <span class="number">7</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">stable_sort</span>(a + <span class="number">1</span>, a + tot + <span class="number">1</span>, cmp2);</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= tot; i++) <span class="built_in">printf</span>(<span class="string">"%s\n"</span>, ans[a[i].ans]);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h3 id="T3"><a href="#T3" class="headerlink" title="T3"></a>T3</h3><p>出题人语文显然需要重修。</p><p>这道题是什么呢,大概就是给一个数 $m$,要求从 $1\sim m$ 中找到一个数 $n$ 使得 $1\sim n$ 中与 $m$ 互质的数的数量与 $n$ 之比最小。</p><p>数据范围是 $1\le m\le 10^{40}$,这不仅告诉我们要开高精,还告诉我们这题肯定有一些奇奇怪怪的性质。</p><p>通过分析样例:</p><p>样例输入 1:<code>10</code></p><p>样例输出 1:<code>6</code></p><p>$6=2\times 3$</p><p>也就是 $3$ 及以内的所有质数相乘。</p><p>样例输入 2:<code>10000000000</code></p><p>样例输出 2:<code>6469693230</code></p><p>$6469693230=2×3×5×7×11×13×17×19×23×29$</p><p>也就是 $29$ 及以内的质数相乘。<del>别问我要怎么看出来,这是 zm 说的,我也不知道。</del></p><p>为什么是 $29$ 呢?因为如果取 $31$ 的话,就超过 $m$ 了,而选用 $29$ 是不超过 $m$ 中最大的那个。</p><p>到这里思路就很明显了:线性筛质数,然后疯狂相乘找答案。时间复杂度是 $O\text{(质数的个数)}$,绝对不会超过 $10^5$。</p><p>需要的高精是高精乘和高精比较,你们爱复制板子就去复制板子吧。<del>反正我也是复制的板子。</del></p><p>代码:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><string></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><iostream></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxn = (<span class="type">int</span>)<span class="number">1e5</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line">string m;</span><br><span class="line"><span class="type">long</span> <span class="type">long</span> g[maxn], tot;</span><br><span class="line"><span class="type">bool</span> f[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Prime</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">2</span>; i <= maxn >> <span class="number">1</span>; i++) {</span><br><span class="line"> <span class="keyword">if</span> (!f[i]) g[++tot] = i;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j <= tot; j++) {</span><br><span class="line"> <span class="type">long</span> <span class="type">long</span> t = i * g[j];</span><br><span class="line"> <span class="keyword">if</span> (t > maxn) <span class="keyword">break</span>;</span><br><span class="line"> f[t] = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> (!(i % g[j])) <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function">string <span class="title">mul</span><span class="params">(string a1, string b1)</span> </span>{</span><br><span class="line"> <span class="type">int</span> a[<span class="number">10005</span>] = {}, b[<span class="number">10005</span>] = {}, c[<span class="number">10005</span>] = {};</span><br><span class="line"> <span class="keyword">if</span> (a1 == <span class="string">"0"</span> || b1 == <span class="string">"0"</span>) <span class="keyword">return</span> <span class="string">"0"</span>;</span><br><span class="line"> string c1;</span><br><span class="line"> <span class="type">int</span> lena = a1.<span class="built_in">size</span>();</span><br><span class="line"> <span class="type">int</span> lenb = b1.<span class="built_in">size</span>();</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < lena; i++) a[lena - i] = a1[i] - <span class="string">'0'</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < lenb; i++) b[lenb - i] = b1[i] - <span class="string">'0'</span>;</span><br><span class="line"> <span class="type">int</span> lenc;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i <= lena; i++) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j <= lenb; j++) {</span><br><span class="line"> lenc = i + j - <span class="number">1</span>;</span><br><span class="line"> c[lenc] += a[i] * b[j];</span><br><span class="line"> c[lenc + <span class="number">1</span>] += c[lenc] / <span class="number">10</span>;</span><br><span class="line"> c[lenc] %= <span class="number">10</span>;</span><br><span class="line"> lenc++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> lenc = lena + lenb;</span><br><span class="line"> <span class="keyword">while</span> (!c[lenc]) lenc--;</span><br><span class="line"> <span class="keyword">while</span> (lenc >= <span class="number">1</span>) c1 += c[lenc--] + <span class="string">'0'</span>;</span><br><span class="line"> <span class="keyword">return</span> c1;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">Max</span><span class="params">(string x, string y)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(x.<span class="built_in">size</span>() > y.<span class="built_in">size</span>()) <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(x.<span class="built_in">size</span>() < y.<span class="built_in">size</span>()) <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> <span class="type">int</span> len = x.<span class="built_in">size</span>();</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i <len; i++) {</span><br><span class="line"> <span class="keyword">if</span>(x[i] > y[i]) <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(x[i] < y[i]) <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function">string <span class="title">str</span><span class="params">(<span class="type">int</span> x)</span> </span>{</span><br><span class="line"> string a, b;</span><br><span class="line"> <span class="keyword">while</span> (x) {</span><br><span class="line"> a += x % <span class="number">10</span> + <span class="number">48</span>;</span><br><span class="line"> x /= <span class="number">10</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = a.<span class="built_in">size</span>() - <span class="number">1</span>; i >= <span class="number">0</span>; i--) b += a[i];</span><br><span class="line"> <span class="keyword">return</span> b;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">freopen</span>(<span class="string">"flower.in"</span>, <span class="string">"r"</span>, stdin);</span><br><span class="line"> <span class="built_in">freopen</span>(<span class="string">"flower.out"</span>, <span class="string">"w"</span>, stdout);</span><br><span class="line"> cin >> m;</span><br><span class="line"> <span class="built_in">Prime</span>();</span><br><span class="line"> string qwq = <span class="string">"1"</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= maxn - <span class="number">5</span>; i++) {</span><br><span class="line"> string r = qwq;</span><br><span class="line"> qwq = <span class="built_in">mul</span>(<span class="built_in">str</span>(g[i]), qwq);</span><br><span class="line"> <span class="keyword">if</span>(<span class="built_in">Max</span>(qwq, m)) {</span><br><span class="line"> cout << r;</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h3 id="T4"><a href="#T4" class="headerlink" title="T4"></a>T4</h3><p>LIS 板子题,LIS 普通版板子都能写挂我也是服了自己了。</p><p>首先初始长度(不斜对角穿)肯定是 $100\times(m+n)$,然后考虑穿对角线的情况。我们把所有允许穿对角线的方块按照 $x$ 值从小到大排序,然后找 $y$ 值的 LIS 即可。</p><p>来自 cgy:<code>sqrt(2)</code> 打成 <code>1.414</code>,精度挂了 $\text{60pts}$。<del>为 cgy 大佬默哀。</del></p><p>LIS 是板子,不需要我讲了吧?</p><p>代码:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><cmath></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><algorithm></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> maxk = <span class="number">1005</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">node</span> { <span class="type">int</span> x, y; } a[maxk];</span><br><span class="line"><span class="type">int</span> m, n, k, qaq, dp[maxk]; <span class="comment">// LIS</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">cmp</span><span class="params">(node x, node y)</span> </span>{ <span class="keyword">return</span> x.x < y.x; }</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">freopen</span>(<span class="string">"metro.in"</span>, <span class="string">"r"</span>, stdin);</span><br><span class="line"> <span class="built_in">freopen</span>(<span class="string">"metro.out"</span>, <span class="string">"w"</span>, stdout);</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d %d %d\n"</span>, &m, &n, &k);</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i <= k; i++) <span class="built_in">scanf</span>(<span class="string">"%d %d"</span>, &a[i].x, &a[i].y);</span><br><span class="line"> <span class="built_in">stable_sort</span>(a + <span class="number">1</span>, a + k + <span class="number">1</span>, cmp);</span><br><span class="line"> <span class="comment">//LIS</span></span><br><span class="line"> dp[<span class="number">1</span>] = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">2</span>; i <= k; i++) {</span><br><span class="line"> <span class="type">int</span> t = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">1</span>; j <= i; j++) {</span><br><span class="line"> <span class="keyword">if</span>(a[j].y < a[i].y) t = <span class="built_in">max</span>(t, dp[j] + <span class="number">1</span>);</span><br><span class="line"> qaq = <span class="built_in">max</span>(qaq, t);</span><br><span class="line"> }</span><br><span class="line"> dp[i] = t;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d"</span>, (<span class="type">int</span>)<span class="built_in">round</span>(((m + n) * <span class="number">100</span> - qaq * (<span class="number">200</span> - <span class="number">100</span> * (<span class="type">long</span> <span class="type">double</span>)<span class="built_in">sqrt</span>(<span class="number">2</span>)))));</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><h3 id="T5"><a href="#T5" class="headerlink" title="T5"></a>T5</h3><p>骗分能拿 $\text{30pts}$:如果修改的次数大于等于掉头指令的个数,就把所有掉头改成前进,然后疯狂改一个指令根据奇偶性判断是不是能改到前进指令从而判断答案。</p><p>正解是 dp:</p><ul><li><p>$dp_{i,j,0,0/1}$ 代表执行前 $i$ 条指令,改 $j$ 次指令,目前头朝正轴方向,在 正数区/负数区 离原点的最远距离。</p></li><li><p>$dp_{i,j,1,0/1}$ 代表执行前 $i$ 条指令,改 $j$ 次指令,目前头朝负轴方向,在 正数区/负数区 离原点的最远距离。</p></li></ul><p>代码鸽掉了。</p>]]></content>
<summary type="html">挂大分,缺大德(狗头)</summary>
<category term="考试总结" scheme="https://blog.liynw.top/categories/%E8%80%83%E8%AF%95%E6%80%BB%E7%BB%93/"/>
<category term="动态规划" scheme="https://blog.liynw.top/tags/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/"/>
<category term="贪心" scheme="https://blog.liynw.top/tags/%E8%B4%AA%E5%BF%83/"/>
<category term="高精度" scheme="https://blog.liynw.top/tags/%E9%AB%98%E7%B2%BE%E5%BA%A6/"/>
<category term="模拟" scheme="https://blog.liynw.top/tags/%E6%A8%A1%E6%8B%9F/"/>
<category term="数学" scheme="https://blog.liynw.top/tags/%E6%95%B0%E5%AD%A6/"/>
</entry>
</feed>