-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
1398 lines (674 loc) · 334 KB
/
search.xml
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
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>P7687 题解</title>
<link href="/2024/11/08/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P7687%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/11/08/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P7687%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>一个通信网络包含若干个节点,以及若干条直接连接这些节点的双向<strong>通信线路</strong>。已知所研究的通信网络是连通的,即:任意一对节点之间都存在(若干条<strong>通信线路</strong>首尾相接而成的)<strong>通信路径</strong>。</p><p>一些节点会向所有节点(包括它自己)提供 <spanclass="math inline">\(A\)</span>类型服务,还有一些节点会向所有节点(包括它自己)提供 <spanclass="math inline">\(B\)</span>类型服务。一个节点可能会同时提供两种类型的服务。每个节点都必须要访问这两种服务。</p><p>当一条<strong>通信线路</strong>断开时,可能会出现某个节点不能访问某种服务的情况。(即:存在某个节点以及某种服务,使得不存在任何提供该类型服务,且与该节点连通的节点)我们称会造成这种情况的<strong>通信线路</strong>为<strong>关键通信线路</strong>。</p><p>你的任务是,写一个程序计算有多少条<strong>关键通信线路</strong>,并求出每条<strong>关键通信线路</strong>所连接的两个端点。</p><h2 id="思路">思路</h2><p>答案肯定是割边。</p><p>我们可以先用 tarjan 求出所有的割边,然后我们在求 tarjan的时候维护出此节点树中服务 <span class="math inline">\(A\)</span> 和<span class="math inline">\(B\)</span> 的数量。</p><p>如果此节点不服务 <span class="math inline">\(A\)</span> 或 <spanclass="math inline">\(B\)</span>,或者 <spanclass="math inline">\(A\)</span> 或 <spanclass="math inline">\(B\)</span>的服务他全部都包揽了,那么这条边肯定是割边。</p><p>原因很好想。如果这条边谁都不服务,如果把这条边去掉,那么其余子树就无法到达该集合中任意一点。如果这条边把<span class="math inline">\(A\)</span> 或 <spanclass="math inline">\(B\)</span>的任务全部包揽了(打工仔...),如果把这条边去掉,那人家就没法服务了啊!</p><h2 id="代码">代码</h2><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></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><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> N = <span class="number">100010</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m, a, b, suma[N], sumb[N], cnt, dfn[N], low[N];</span><br><span class="line"><span class="type">bool</span> vis[N];</span><br><span class="line">vector<<span class="type">int</span>> e[N];</span><br><span class="line">vector<pair<<span class="type">int</span>, <span class="type">int</span>>> vt;</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> fa)</span> </span>{</span><br><span class="line"> dfn[u] = low[u] = ++cnt;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">auto</span> v : e[u]) {</span><br><span class="line"> <span class="keyword">if</span> (v != fa) {</span><br><span class="line"> <span class="keyword">if</span> (!dfn[v]) {</span><br><span class="line"> <span class="built_in">tarjan</span>(v, u);</span><br><span class="line"> suma[u] += suma[v];</span><br><span class="line"> sumb[u] += sumb[v];</span><br><span class="line"> low[u] = <span class="built_in">min</span>(low[u], low[v]);</span><br><span class="line"> <span class="keyword">if</span>(low[v] > dfn[u] && (suma[v] == <span class="number">0</span> || sumb[v] == <span class="number">0</span> || suma[v] == a || sumb[v] == b)) </span><br><span class="line"> vt.<span class="built_in">push_back</span>({u, v});</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> low[u] = <span class="built_in">min</span>(low[u], dfn[v]);</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><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"> cin >> n >> m >> a >> b;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>, x; i <= a; i++) {</span><br><span class="line"> cin >> x;</span><br><span class="line"> suma[x] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>, x; i <= b; i++) {</span><br><span class="line"> cin >> x;</span><br><span class="line"> sumb[x] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i <= m; i++) {</span><br><span class="line"> <span class="type">int</span> x, y;</span><br><span class="line"> cin >> x >> y;</span><br><span class="line"> e[x].<span class="built_in">push_back</span>(y);</span><br><span class="line"> e[y].<span class="built_in">push_back</span>(x);</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"> cout << vt.<span class="built_in">size</span>() << <span class="string">'\n'</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">auto</span> [x, y] : vt) {</span><br><span class="line"> cout << x << <span class="string">' '</span> << y << <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>
<categories>
<category> 洛谷题解 </category>
</categories>
<tags>
<tag> 图论 </tag>
<tag> Tarjan </tag>
<tag> 割边 </tag>
</tags>
</entry>
<entry>
<title>UVA10199题解</title>
<link href="/2024/11/01/UVA%E9%A2%98%E8%A7%A3/UVA10199%E9%A2%98%E8%A7%A3/"/>
<url>/2024/11/01/UVA%E9%A2%98%E8%A7%A3/UVA10199%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>给定一个由字符串构成的图,你需要求出这个图中的割点并输出。</p><h2 id="思路">思路</h2><p>和割点<ahref="https://www.luogu.com.cn/problem/P3388">模版</a>差不多,我们只需要吧字符串转换成数字即可。</p><p>最后需要注意,每组数据之间需要空一行(坑死了)。</p><h2 id="代码">代码</h2><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"><bits/stdc++.h></span></span></span><br><span class="line"></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> N = <span class="number">110</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m, ans;</span><br><span class="line"><span class="type">int</span> dfn[N], low[N], cnt, root;</span><br><span class="line"><span class="type">bool</span> flag[N];</span><br><span class="line">vector<<span class="type">int</span>> e[N];</span><br><span class="line">map<string, <span class="type">int</span>> mp;</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> </span>{</span><br><span class="line"> dfn[u] = low[u] = ++cnt;</span><br><span class="line"> <span class="type">int</span> num = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">auto</span> v : e[u]) {</span><br><span class="line"> <span class="keyword">if</span> (!dfn[v]) {</span><br><span class="line"> <span class="built_in">tarjan</span>(v);</span><br><span class="line"> low[u] = <span class="built_in">min</span>(low[u], low[v]);</span><br><span class="line"> num++;</span><br><span class="line"> <span class="keyword">if</span> (low[v] >= dfn[u]) {</span><br><span class="line"> <span class="keyword">if</span> (u != root || num > <span class="number">1</span>) {</span><br><span class="line"> ans += !flag[u];</span><br><span class="line"> flag[u] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> low[u] = <span class="built_in">min</span>(low[u], dfn[v]);</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">void</span> <span class="title">init</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"> e[i].<span class="built_in">clear</span>();</span><br><span class="line"> mp.<span class="built_in">clear</span>();</span><br><span class="line"> cnt = <span class="number">0</span>, ans = <span class="number">0</span>;</span><br><span class="line"> <span class="built_in">memset</span>(flag, <span class="number">0</span>, <span class="keyword">sizeof</span> flag);</span><br><span class="line"> <span class="built_in">memset</span>(dfn, <span class="number">0</span>, <span class="keyword">sizeof</span> dfn);</span><br><span class="line"> <span class="built_in">memset</span>(low, <span class="number">0</span>, <span class="keyword">sizeof</span> low);</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"> cin.<span class="built_in">tie</span>(<span class="number">0</span>)-><span class="built_in">sync_with_stdio</span>(<span class="number">0</span>);</span><br><span class="line"> <span class="type">int</span> tot = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span> (cin >> n && n) {</span><br><span class="line"> tot++;</span><br><span class="line"> <span class="built_in">init</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"> string s;</span><br><span class="line"> cin >> s;</span><br><span class="line"> mp[s] = i;</span><br><span class="line"> }</span><br><span class="line"> cin >> m;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i <= m; i++) {</span><br><span class="line"> string s1, s2;</span><br><span class="line"> cin >> s1 >> s2;</span><br><span class="line"> e[mp[s1]].<span class="built_in">push_back</span>(mp[s2]);</span><br><span class="line"> e[mp[s2]].<span class="built_in">push_back</span>(mp[s1]);</span><br><span class="line"> }</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> (!dfn[i]) {</span><br><span class="line"> root = i;</span><br><span class="line"> <span class="built_in">tarjan</span>(i);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (tot != <span class="number">1</span>) </span><br><span class="line"> cout << <span class="string">'\n'</span>;</span><br><span class="line"> cout << <span class="string">"City map #"</span> << tot << <span class="string">": "</span> << ans << <span class="string">" camera(s) found\n"</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">auto</span> [s, i] : mp) {</span><br><span class="line"> <span class="keyword">if</span> (flag[i]) {</span><br><span class="line"> cout << s << <span class="string">'\n'</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 class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> UVA题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 图论 </tag>
<tag> Tarjan </tag>
<tag> 割点 </tag>
</tags>
</entry>
<entry>
<title>强联通分量学习笔记</title>
<link href="/2024/11/01/%E6%97%A5%E5%B8%B8%E7%AC%94%E8%AE%B0/%E5%BC%BA%E8%81%94%E9%80%9A%E5%88%86%E9%87%8F%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<url>/2024/11/01/%E6%97%A5%E5%B8%B8%E7%AC%94%E8%AE%B0/%E5%BC%BA%E8%81%94%E9%80%9A%E5%88%86%E9%87%8F%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/</url>
<content type="html"><![CDATA[<h2 id="概念">概念</h2><p>点双联通:在无向图中,删除一个点(不是 <spanclass="math inline">\(x\)</span> 或着 <spanclass="math inline">\(y\)</span>)后,点 <spanclass="math inline">\(x\)</span> 和 <spanclass="math inline">\(y\)</span> 仍然连通,那么称 <spanclass="math inline">\(x\)</span> 和 <spanclass="math inline">\(y\)</span> 是点双联通的。</p><p>边双联通:在无向图中,删除一条边后,点 <spanclass="math inline">\(x\)</span> 和 <spanclass="math inline">\(y\)</span> 仍然连通,那么称 <spanclass="math inline">\(x\)</span> 和 <spanclass="math inline">\(y\)</span> 是边双联通的。</p><h2 id="性质">性质</h2><ol type="1"><li>点双联通不具有传递性,而边双联通具有传递性。</li></ol><h2 id="割点">割点</h2><h3 id="定义">定义</h3><p>在无向图中,若删除一个点后,图不再连通,那么称这个点为割点。</p><h3 id="结论">结论</h3><p>至少有 <span class="math inline">\(3\)</span>个点的无向图,才可能存在割点。</p><h3 id="求割点">求割点</h3><p>若搜索树上,有 <span class="math inline">\(x\)</span> 到 <spanclass="math inline">\(y\)</span> 的连边,也就是当 <spanclass="math inline">\(low_y \le dfn_x\)</span> 时,说明 <spanclass="math inline">\(y\)</span> 能到达的最小时间戳在 <spanclass="math inline">\(x\)</span> 的时间戳上之上,<spanclass="math inline">\(y\)</span> 被 <spanclass="math inline">\(x\)</span> 与 <spanclass="math inline">\(x\)</span> 之间的节点“隔开”,<spanclass="math inline">\(x\)</span> 就可能是割点。</p><p>只要 <span class="math inline">\(x\)</span> 不是搜索树的根节点,或者<span class="math inline">\(x\)</span> 是根节点,但是 <spanclass="math inline">\(x\)</span> 的子节点个数大于 <spanclass="math inline">\(1\)</span>,那么 <spanclass="math inline">\(x\)</span> 就是割点。</p><h3 id="代码洛谷-p3388">代码(洛谷 P3388)</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></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><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> N = <span class="number">2e4</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m, root, cnt, ans;</span><br><span class="line"><span class="type">int</span> dfn[N], low[N];</span><br><span class="line"><span class="type">bool</span> flag[N];</span><br><span class="line">vector<<span class="type">int</span>> e[N];</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> </span>{</span><br><span class="line"> dfn[u] = low[u] = ++cnt;</span><br><span class="line"> <span class="type">int</span> num = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">auto</span> v : e[u]) {</span><br><span class="line"> <span class="keyword">if</span> (!dfn[v]) {</span><br><span class="line"> <span class="built_in">tarjan</span>(v);</span><br><span class="line"> low[u] = <span class="built_in">min</span>(low[u], low[v]);</span><br><span class="line"> num++;</span><br><span class="line"> <span class="keyword">if</span> (low[v] >= dfn[u]) {</span><br><span class="line"> <span class="keyword">if</span> (u != root || num > <span class="number">1</span>) {</span><br><span class="line"> ans += !flag[u];</span><br><span class="line"> flag[u] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> low[u] = <span class="built_in">min</span>(low[u], dfn[v]);</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">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> cin >> n >> m;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i <= m; i++) {</span><br><span class="line"> <span class="type">int</span> u, v;</span><br><span class="line"> cin >> u >> v;</span><br><span class="line"> e[u].<span class="built_in">push_back</span>(v);</span><br><span class="line"> e[v].<span class="built_in">push_back</span>(u);</span><br><span class="line"> }</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> (!dfn[i]) {</span><br><span class="line"> root = i;</span><br><span class="line"> <span class="built_in">tarjan</span>(i);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> cout << ans << <span class="string">'\n'</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> (flag[i]) {</span><br><span class="line"> cout << i << <span class="string">' '</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><h2 id="割边">割边</h2><h3 id="割边的性质">割边的性质</h3><p>割边一定不在环上,在环上的一定不是割边。</p><p>割边通常是“必经边”的问题。</p><p>割边删除后恰好增加 <span class="math inline">\(1\)</span>个联通块。</p><h3 id="割边的判定">割边的判定</h3><p>维护 <span class="math inline">\(dfn_x\)</span> 和 <spanclass="math inline">\(low_x\)</span>,对于 <spanclass="math inline">\(x\)</span> 到 <spanclass="math inline">\(y\)</span> 的边,若 <spanclass="math inline">\(low_y > dfn_x\)</span></p>]]></content>
<categories>
<category> 笔记 </category>
</categories>
<tags>
<tag> 笔记 </tag>
<tag> 强联通分量 </tag>
</tags>
</entry>
<entry>
<title>P4316 题解</title>
<link href="/2024/10/25/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P4316%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P4316%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>给出张 <span class="math inline">\(n\)</span> 个点 <spanclass="math inline">\(m\)</span> 条边的有向无环图,起点为 <spanclass="math inline">\(1\)</span>,终点为 <spanclass="math inline">\(n\)</span>,每条边都有一个长度,并且从起点出发能够到达所有的点,所有的点也都能够到达终点,你需要求出从起点走到终点的所经过的路径总长度期望是多少?。</p><h2 id="思路">思路</h2><p>这道题是图上概率 dp 的板子,下面会讲出我的理解。</p><p>图上概率dp的状态一般为 <span class="math inline">\(dp_u\)</span>表示从 <span class="math inline">\(u\)</span> 到 <spanclass="math inline">\(n\)</span> 的期望,转移为 <spanclass="math inline">\(dp_u = \sum p_{u \to v} \times (dp_v + w_{u \tov})\)</span> 。</p><p>我们来找这道题的 <span class="math inline">\(p\)</span> 和 <spanclass="math inline">\(w\)</span>。</p><p>这道题的 <span class="math inline">\(p\)</span> 就是 <spanclass="math inline">\(\frac{1}{degree_u}\)</span>,其中 <spanclass="math inline">\(degree_u\)</span> 表示点 <spanclass="math inline">\(u\)</span> 的度数。</p><p><span class="math inline">\(w\)</span> 就是题目中给出的边的长度。</p><p>但这样有一个问题,如何实现?</p><p>由于这是一个有向图,我们就可以用拓扑排序,建反图,然后在拓扑排序中做dp,但需要注意,由于我们建的是反图,所以我们的dp也要倒着来。</p><h2 id="代码">代码</h2><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></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><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> N = <span class="number">1e5</span> + <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m, in[N], cnt[N];</span><br><span class="line"><span class="type">double</span> dp[N];</span><br><span class="line">vector<pair<<span class="type">int</span>, <span class="type">int</span>>> e[N];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">topsort</span><span class="params">()</span> </span>{</span><br><span class="line"> queue<<span class="type">int</span>> q;</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> (!in[i]) q.<span class="built_in">push</span>(i);</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="type">int</span> u = q.<span class="built_in">front</span>();</span><br><span class="line"> q.<span class="built_in">pop</span>();</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">auto</span> [v, w] : e[u]) {</span><br><span class="line"> dp[v] += (dp[u] + w) / (cnt[v] * <span class="number">1.0</span>);</span><br><span class="line"> <span class="keyword">if</span> (--in[v] == <span class="number">0</span>) q.<span class="built_in">push</span>(v);</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">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> cin >> n >> m;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i <= m; i++) {</span><br><span class="line"> <span class="type">int</span> x, y, z;</span><br><span class="line"> cin >> x >> y >> z;</span><br><span class="line"> e[y].<span class="built_in">push_back</span>({x, z});</span><br><span class="line"> in[x]++;</span><br><span class="line"> cnt[x]++;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">topsort</span>();</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%.2lf\n"</span>, dp[<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>]]></content>
<categories>
<category> 洛谷题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 动态规划dp </tag>
<tag> 概率与期望 </tag>
</tags>
</entry>
<entry>
<title>DP U 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20U%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20U%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>对 <spanclass="math inline">\(N\)</span> 个物品任意分组,如果第 <spanclass="math inline">\(i\)</span> 个物品和 第 <spanclass="math inline">\(j\)</span> 个物品分在一组,会产生 <spanclass="math inline">\(a_{i,j}\)</span> 的得分,最大化得分之和。 >注意: > > <span class="math inline">\((i,j)\)</span> 和 <spanclass="math inline">\((j,i)\)</span> 的贡献只计算一次。</p><h2 id="思路">思路</h2><p>定义状态:<span class="math inline">\(dp_i\)</span>表示二进制下状态为 <span class="math inline">\(i\)</span>能获得的最大得分和。</p><p>状态转移方程: <span class="math display">\[dp_i = \max_{j \in i} (dp_j + dp_{i \oplus j})\]</span></p><p>答案为 <span class="math inline">\(dp_{2^n - 1}\)</span>。</p><p>时间复杂度:<span class="math inline">\(\mathcal O (2^{n} -1)\)</span>。</p><h2 id="代码">代码</h2><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></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><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">long</span> <span class="type">long</span> n, a[<span class="number">30</span>][<span class="number">30</span>], dp[<span class="number">1</span> << <span class="number">17</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"> cin >> n;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < n; i++) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">0</span>; j < n; j++) {</span><br><span class="line"> cin >> a[i][j];</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 < (<span class="number">1</span> << n); i++) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">0</span>; j < n; j++) {</span><br><span class="line"> <span class="keyword">if</span> (i >> j & <span class="number">1</span>) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> k = j + <span class="number">1</span>; k < n; k++) {</span><br><span class="line"> <span class="keyword">if</span> (i >> k & <span class="number">1</span>) {</span><br><span class="line"> dp[i] += a[j][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="keyword">for</span> (<span class="type">int</span> j = i; j; j = (j - <span class="number">1</span>) & i) {</span><br><span class="line"> dp[i] = <span class="built_in">max</span>(dp[i], dp[j] + dp[j ^ i]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> cout << dp[(<span class="number">1</span> << 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>]]></content>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 动态规划dp </tag>
<tag> 状态压缩dp </tag>
</tags>
</entry>
<entry>
<title>DP Q 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20Q%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20Q%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>你有 <span class="math inline">\(n\)</span>朵花,每朵花有一个高度和美丽度,你需要选择一些花,是的他们的高度单调递增,请求出他们的美丽之和的最大值。## 思路</p><p>定义状态:<span class="math inline">\(dp_i\)</span> 表示以 <spanclass="math inline">\(i\)</span> 结尾的花美丽之和的最大值。</p><p>状态转移方程: <span class="math display">\[dp_i = \max_{j \in n}^{a_j \le a_i} (dp_j) + a_i\]</span></p><p>但如果我们直接这么做的话,我们会 T 飞。可以看到转移式子中有一个求<spanclass="math inline">\(max\)</span>,这就是导致我们慢的原因,我们可以用树状数组或线段树来维护这个求<span class="math inline">\(max\)</span> 值。</p><p>答案为 <span class="math inline">\(\max_{i = 1}^{n}dp_i\)</span>。</p><p>时间复杂度:<span class="math inline">\(\mathcal O (n \logn)\)</span>。</p><h2 id="代码">代码</h2><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"><bits/stdc++.h></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> lowbit(x) (x & -x)</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">using</span> ll = <span class="type">long</span> <span class="type">long</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">2e5</span> + <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n;</span><br><span class="line">ll a[N], b[N], dp[N], sum[N], ans;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">add</span><span class="params">(<span class="type">int</span> x, ll k)</span> </span>{</span><br><span class="line"> <span class="keyword">while</span> (x <= N - <span class="number">10</span>) {</span><br><span class="line"> sum[x] = <span class="built_in">max</span>(sum[x], 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><br><span class="line"></span><br><span class="line"><span class="function">ll <span class="title">query</span><span class="params">(<span class="type">int</span> x)</span> </span>{</span><br><span class="line"> ll res = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span> (x) {</span><br><span class="line"> res = <span class="built_in">max</span>(res, sum[x]);</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> res;</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"> cin >> 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++) cin >> a[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++) cin >> b[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++) {</span><br><span class="line"> dp[i] = <span class="built_in">query</span>(a[i] - <span class="number">1</span>) + b[i];</span><br><span class="line"> <span class="built_in">add</span>(a[i], dp[i]);</span><br><span class="line"> ans = <span class="built_in">max</span>(ans, dp[i]);</span><br><span class="line"> }</span><br><span class="line"> cout << ans << endl;</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>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 动态规划dp </tag>
<tag> 线段树 </tag>
<tag> 树状数组 </tag>
</tags>
</entry>
<entry>
<title>DP P 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20P%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20P%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>给一棵树,每一个点可以染成黑色或白色,任意两个相邻节点不能都是黑色,求方案数,结果对<span class="math inline">\(10^9 + 7\)</span> 取模。</p><h2 id="思路">思路</h2><p>定义状态:<span class="math inline">\(dp_{i, 0/1}\)</span> 表示以<span class="math inline">\(i\)</span>为根的子树染白色或黑色的方案数。</p><p>状态转移方程: <span class="math display">\[\begin{cases}dp_{u, 0} = \prod_{v \in u} dp_{v, 0} + dp_{v, 1} \\dp_{u, 1} = \prod_{v \in u} dp_{v, 0}\end{cases}\]</span></p><p>答案为 <span class="math inline">\(dp_{1, 0} + dp_{1,1}\)</span>。</p><p>时间复杂度:<span class="math inline">\(\mathcal O (n + m)\)</span>。## 代码</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"><bits/stdc++.h></span></span></span><br><span class="line"></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> N = <span class="number">1e5</span> + <span class="number">10</span>;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> mod = <span class="number">1e9</span> + <span class="number">7</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, dp[N][<span class="number">2</span>];</span><br><span class="line">vector<<span class="type">int</span>> e[N];</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"> dp[u][<span class="number">0</span>] = dp[u][<span class="number">1</span>] = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">auto</span> v : e[u]) {</span><br><span class="line"> <span class="keyword">if</span> (v == fa) <span class="keyword">continue</span>;</span><br><span class="line"> <span class="built_in">dfs</span>(v, u);</span><br><span class="line"> dp[u][<span class="number">0</span>] = <span class="number">1LL</span> * dp[u][<span class="number">0</span>] * (dp[v][<span class="number">0</span>] + dp[v][<span class="number">1</span>]) % mod;</span><br><span class="line"> dp[u][<span class="number">1</span>] = <span class="number">1LL</span> * dp[u][<span class="number">1</span>] * dp[v][<span class="number">0</span>] % mod;</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">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> cin >> 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="type">int</span> u, v;</span><br><span class="line"> cin >> u >> v;</span><br><span class="line"> e[u].<span class="built_in">push_back</span>(v);</span><br><span class="line"> e[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 class="number">0</span>);</span><br><span class="line"> cout << (dp[<span class="number">1</span>][<span class="number">0</span>] + dp[<span class="number">1</span>][<span class="number">1</span>]) % mod << endl;</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>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 动态规划dp </tag>
<tag> 树形dp </tag>
</tags>
</entry>
<entry>
<title>DP O 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20O%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20O%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>给定二分图,两个集合都有 <spanclass="math inline">\(N\)</span> 个点,<spanclass="math inline">\(a_{i,j} = 1\)</span> 表示第一个集合第<spanclass="math inline">\(i\)</span> 个点与第二个集合第 <spanclass="math inline">\(j\)</span> 个点连边。</p><p>求二分图完备匹配数,答案对 <span class="math inline">\(10^9 +7\)</span> 取模。</p><h2 id="思路">思路</h2><p>定义状态:<span class="math inline">\(dp_{i, j}\)</span> 表示有 <spanclass="math inline">\(i\)</span> 点已经匹配完毕,匹配的状态为 <spanclass="math inline">\(j\)</span>。</p><p>状态转移方程: <span class="math display">\[dp_{i, j} = \sum dp_{i - 1, j | 2^k}\]</span></p><p>答案为 <span class="math inline">\(dp_{n, 2^n - 1}\)</span></p><p>时间复杂度:<span class="math inline">\(\mathcal O (n \times2^n)\)</span>。</p><h2 id="代码">代码</h2><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></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 class="type">const</span> <span class="type">int</span> mod = <span class="number">1e9</span> + <span class="number">7</span>;</span><br><span class="line"><span class="type">int</span> n, a[<span class="number">30</span>][<span class="number">30</span>], dp[<span class="number">30</span>][(<span class="number">1</span> << <span class="number">21</span>) + <span class="number">10</span>];</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"> cin >> n;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i < n;i++){</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">0</span>;j < n;j++){</span><br><span class="line"> cin >> a[i][j];</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><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i < n;i++){</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">0</span>;j < (<span class="number">1</span> << n);j++){</span><br><span class="line"> <span class="keyword">if</span>(__builtin_popcount(j) == i){</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> k = <span class="number">0</span>;k < n;k++){</span><br><span class="line"> <span class="keyword">if</span>(a[i][k] && (j & (<span class="number">1</span> << k)) == <span class="number">0</span>){</span><br><span class="line"> dp[i + <span class="number">1</span>][j | (<span class="number">1</span> << k)] = (dp[i + <span class="number">1</span>][j | (<span class="number">1</span> << k)] + dp[i][j]) % mod;</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><br><span class="line"> cout << dp[n][(<span class="number">1</span> << 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>]]></content>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 动态规划dp </tag>
<tag> 状态压缩dp </tag>
</tags>
</entry>
<entry>
<title>DP N 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20N%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20N%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>你有 <span class="math inline">\(n\)</span>堆石子,你每次可以合并相邻的石子,你要付出 <spanclass="math inline">\(a_i + a_{i + 1}\)</span> 代价,求将 <spanclass="math inline">\(n\)</span> 堆石子合并成一堆的最小代价。 ##思路</p><p>定义状态:<span class="math inline">\(dp_{l, r}\)</span> 表示从 <spanclass="math inline">\(l\)</span> 到 <spanclass="math inline">\(r\)</span> 合并成一堆需要付出的最小代价。</p><p>状态转移方程: <span class="math display">\[dp_{l, r} = \min_{k = l}^{r - 1} (dp_{l, k} + dp_{k + 1, r}) + \sum_{i =l}^{r} a_i\]</span></p><p>我们可以将后面的 <span class="math inline">\(\sum_{i = l}^{r}a_i\)</span> 做一个前缀和预处理,时间复杂度为 <spanclass="math inline">\(\mathcal O (n ^ 3)\)</span>。</p><h2 id="代码">代码</h2><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"><bits/stdc++.h></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="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> N = <span class="number">410</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, a[N], dp[N][N];</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"> cin >> n;</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="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> cin >> a[i];</span><br><span class="line"> dp[i][i] = <span class="number">0</span>;</span><br><span class="line"> a[i] += a[i - <span class="number">1</span>];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">2</span>; i <= n; i++) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> l = <span class="number">1</span>, r = i; r <= n; l++, r++) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> k = l; k < r; k++) {</span><br><span class="line"> dp[l][r] = <span class="built_in">min</span>(dp[l][r], dp[l][k] + dp[k + <span class="number">1</span>][r]);</span><br><span class="line"> }</span><br><span class="line"> dp[l][r] += a[r] - a[l - <span class="number">1</span>];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> cout << dp[<span class="number">1</span>][n] << endl;</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>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 区间dp </tag>
<tag> 动态规划dp </tag>
</tags>
</entry>
<entry>
<title>DP M 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20M%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20M%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>你有 <span class="math inline">\(k\)</span> 颗糖,你要分给 <spanclass="math inline">\(n\)</span> 个人,不能有剩余,每个人至多分 <spanclass="math inline">\(a_i\)</span> 个,至少分 <spanclass="math inline">\(0\)</span> 个,请问有多少种方案。</p><h2 id="思路">思路</h2><p>定义状态:<span class="math inline">\(dp_{i, j}\)</span> 表示前 <spanclass="math inline">\(i\)</span> 个人,分了 <spanclass="math inline">\(j\)</span> 颗糖的方案。</p><p>状态转移方程: <span class="math display">\[dp_{i, j} = \sum_{k = \max(0, j - a_{i - 1})}^{j} dp_{i - 1, k}\]</span></p><p>但如果我们这么做,时间复杂度会达到 <spanclass="math inline">\(\mathcal O (n \timesk^2)\)</span>,显然过不了。我们让我们程序跑不快的是我们有重新枚举前面的dp,我们发现我们枚举的是一段连续的区间,所以我们就可以用前缀和进行优化。</p><p>答案为 <span class="math inline">\(dp_{n, k}\)</span>。</p><p>时间复杂度:<span class="math inline">\(\mathcal O (n \timesk)\)</span>。</p><h2 id="代码">代码</h2><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></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">define</span> int long long</span></span><br><span class="line"></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> N = <span class="number">110</span>;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> M = <span class="number">1e5</span> + <span class="number">10</span>;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> mod = <span class="number">1e9</span> + <span class="number">7</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, k, a[N], dp[N][M], sum[N][M];</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"> cin >> n >> k;</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"> cin >> a[i];</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 <= k; i++) {</span><br><span class="line"> sum[<span class="number">0</span>][i] = <span class="number">1</span>;</span><br><span class="line"> }</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][<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line"> sum[i][<span class="number">0</span>] = <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 <= k; j++) {</span><br><span class="line"> dp[i][j] = (sum[i - <span class="number">1</span>][j] - (j - a[i] - <span class="number">1</span> < <span class="number">0</span> ? <span class="number">0</span> : sum[i - <span class="number">1</span>][j - a[i] - <span class="number">1</span>]) + mod) % mod;</span><br><span class="line"> sum[i][j] += (sum[i][j - <span class="number">1</span>] + dp[i][j]) % mod;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> cout << dp[n][k];</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>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 动态规划dp </tag>
<tag> 背包 </tag>
</tags>
</entry>
<entry>
<title>DP K 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20K%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20K%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>给定一个由 <span class="math inline">\(n\)</span> 个整数的集合 <spanclass="math inline">\(A = \{ a_1, a_2, a_3, \dots , a_n\}\)</span>,现在有 <span class="math inline">\(k\)</span>个石子堆,你可以每次取走 <span class="math inline">\(a_i\)</span>个石子堆,问你是先手赢还是后手赢。 ## 思路</p><p>定义状态:<span class="math inline">\(dp_i\)</span> 表示还剩下 <spanclass="math inline">\(i\)</span> 个石子堆事先手赢还是后手赢。</p><p>状态转移方程:</p><p><span class="math display">\[dp_i = dp_{i - a_j} \oplus 1\]</span></p><p>答案为 <span class="math inline">\(dp_m\)</span> 为 <spanclass="math inline">\(1\)</span> 是先手赢,否则后手赢。</p><p>时间复杂度:<span class="math inline">\(\mathcal O (n \timesk)\)</span>。 ## 代码</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></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><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">bool</span> dp[<span class="number">100005</span>];</span><br><span class="line"><span class="type">int</span> n, m, a[<span class="number">100005</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"> cin >> n >> m;</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"> cin >> a[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i <= m; i++) {</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"> dp[i] += i - a[j] >= <span class="number">0</span> && !dp[i - a[j]]; </span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> cout << (dp[m] ? <span class="string">"First"</span> : <span class="string">"Second"</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>]]></content>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 动态规划dp </tag>
<tag> 博弈论 </tag>
</tags>
</entry>
<entry>
<title>DP H 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20H%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20H%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<p>题目算法: #动态规划dp</p><h2 id="题意">题意</h2><p>给定一个 <span class="math inline">\(n \times m\)</span>的矩阵,矩阵里有 <code>.</code> 和 <code>#</code>两种字符,<code>#</code> 不可以走,<code>.</code> 可以走,你需要求出从<span class="math inline">\((1, 1)\)</span> 走到 <spanclass="math inline">\((n, m)\)</span> 有多少种方案。</p><blockquote><p>注意:</p><p>你只能向下或向右走!</p></blockquote><h2 id="思路">思路</h2><p>定义状态:<span class="math inline">\(dp_{i, j}\)</span> 表示从 <spanclass="math inline">\((1, 1)\)</span> 走到 <spanclass="math inline">\((i, j)\)</span> 有多少种方案。</p><p>初始化:<span class="math inline">\(dp_{1, 1} = 1\)</span>。</p><p>状态转移方程: <span class="math display">\[dp_{i, j} = dp_{i - 1, j} + dp_{i, j - 1}\]</span></p><p>答案:<span class="math inline">\(dp_{n, m}\)</span>。</p><p>时间复杂度:<span class="math inline">\(\mathcal O (n \timesm)\)</span>。</p><h2 id="代码">代码</h2><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="meta">#<span class="keyword">include</span> <span class="string"><bits/stdc++.h></span></span></span><br><span class="line"></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> N = <span class="number">1010</span>;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> mod = <span class="number">1e9</span> + <span class="number">7</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m, dp[N][N];</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"> dp[<span class="number">1</span>][<span class="number">1</span>] = <span class="number">1</span>;</span><br><span class="line"> cin >> n >> m;</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">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j <= m; j++) {</span><br><span class="line"> <span class="type">char</span> ch;</span><br><span class="line"> cin >> ch;</span><br><span class="line"> <span class="keyword">if</span> (ch == <span class="string">'.'</span> && !(i == <span class="number">1</span> && j == <span class="number">1</span>)) {</span><br><span class="line"> dp[i][j] = (dp[i - <span class="number">1</span>][j] + dp[i][j - <span class="number">1</span>]) % mod;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> cout << dp[n][m];</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>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 动态规划dp </tag>
</tags>
</entry>
<entry>
<title>DP G 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20G%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20G%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>给定一个 <span class="math inline">\(n\)</span> 个点,<spanclass="math inline">\(m\)</span>条边的的有向图,求最多可以从一个点经过多少条边。</p><h2 id="思路">思路</h2><p>定义状态:<span class="math inline">\(dp_i\)</span> 表示从 <spanclass="math inline">\(i\)</span> 出发,最多能经过多少条边。</p><p>状态转移方程: <span class="math display">\[dp_u = \max(dp_v) + 1\]</span></p><p>答案为:<span class="math inline">\(\max_{i = 1}^{n}dp_i\)</span>。</p><p>时间复杂度:<span class="math inline">\(\mathcal O (n +m)\)</span>。</p><h2 id="代码">代码</h2><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"><bits/stdc++.h></span></span></span><br><span class="line"></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> N = <span class="number">1e5</span> + <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> dp[N], n, m, ans;</span><br><span class="line"><span class="type">bool</span> vis[N];</span><br><span class="line">vector<<span class="type">int</span>> e[N];</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"> <span class="keyword">if</span> (dp[u]) <span class="keyword">return</span>;</span><br><span class="line"> dp[u] = <span class="number">-1</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">auto</span> v : e[u]) {</span><br><span class="line"> <span class="keyword">if</span> (vis[v]) <span class="keyword">continue</span>;</span><br><span class="line"> <span class="built_in">dfs</span>(v);</span><br><span class="line"> dp[u] = <span class="built_in">max</span>(dp[u], dp[v]);</span><br><span class="line"> }</span><br><span class="line"> dp[u]++;</span><br><span class="line"> ans = <span class="built_in">max</span>(ans, dp[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"> cin >> n >> m;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i <= m; i++) {</span><br><span class="line"> <span class="type">int</span> u, v;</span><br><span class="line"> cin >> u >> v;</span><br><span class="line"> e[u].<span class="built_in">push_back</span>(v);</span><br><span class="line"> }</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">dfs</span>(i);</span><br><span class="line"> }</span><br><span class="line"> cout << 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>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 动态规划dp </tag>
<tag> 记忆化搜索 </tag>
</tags>
</entry>
<entry>
<title>DP F 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20F%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20F%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>给定两个字符串,你需要求出两个字符串的最长 LCS,并输出。</p><blockquote><p>什么是 LCS?</p><p>LCS 是最长公共子序列的缩写。</p></blockquote><h2 id="思路">思路</h2><p>定义状态:<span class="math inline">\(dp_{i, j}\)</span>表示第一个字符串前 <span class="math inline">\(i\)</span>个字符和第二个字符串前 <span class="math inline">\(j\)</span>个字符的最长 LCS。</p><p>状态转移方程: <span class="math display">\[dp_{i, j} = \max(dp_{i - 1, j}, dp_{i, j - 1}, dp_{i - 1, j - 1} + 1)\]</span></p><p>答案为 <span class="math inline">\(dp_{lena, lenb}\)</span>。</p><p>时间复杂度:<span class="math inline">\(\mathcal O (lena \timeslenb)\)</span>。</p><h2 id="代码">代码</h2><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"><bits/stdc++.h></span></span></span><br><span class="line"></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> N = <span class="number">3010</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">char</span> s1[N], s2[N], ans[N];</span><br><span class="line"><span class="type">int</span> dp[N][N];</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"> cin >> s1 + <span class="number">1</span> >> s2 + <span class="number">1</span>;</span><br><span class="line"> <span class="type">int</span> n = <span class="built_in">strlen</span>(s1 + <span class="number">1</span>), m = <span class="built_in">strlen</span>(s2 + <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"> <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j <= m; j++) {</span><br><span class="line"> dp[i][j] = <span class="built_in">max</span>(dp[i - <span class="number">1</span>][j], dp[i][j - <span class="number">1</span>]);</span><br><span class="line"> <span class="keyword">if</span> (s1[i] == s2[j]) {</span><br><span class="line"> dp[i][j] = <span class="built_in">max</span>(dp[i][j], dp[i - <span class="number">1</span>][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><br><span class="line"> <span class="type">int</span> i = n, j = m;</span><br><span class="line"> <span class="keyword">while</span> (dp[i][j] > <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">if</span> (s1[i] == s2[j]) {</span><br><span class="line"> ans[dp[i][j]] = s1[i];</span><br><span class="line"> i--;</span><br><span class="line"> j--;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">if</span> (dp[i - <span class="number">1</span>][j] == dp[i][j]) {</span><br><span class="line"> i--;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> j--;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> cout << ans + <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>]]></content>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 动态规划dp </tag>
</tags>
</entry>
<entry>
<title>DP E 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20E%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20E%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>给定 <span class="math inline">\(n\)</span> 个物品,容量为 <spanclass="math inline">\(m\)</span>的背包,每个物品有一个价值和体积,数量只有一个,你需要求出取这些物品<span class="math inline">\(\sum_{i = 1}^{n} w_i \le W\)</span>的前提下最大化 <span class="math inline">\(\sum v_i\)</span>。</p><h2 id="思路">思路</h2><p>虽然跟普通的 01 背包很想,但 <span class="math inline">\(W\)</span>的最大值达到了 <span class="math inline">\(10^9\)</span>所以我们无法用之前的状态,但 <span class="math inline">\(\sum v_i \le10^5\)</span> 所以我们就可以用价值做状态。</p><p>定义转态:<span class="math inline">\(dp_{i, j}\)</span> 表示前 <spanclass="math inline">\(i\)</span> 个物品,选择的总价值为 <spanclass="math inline">\(j\)</span> 的最小重量。</p><p>状态转移方程: <span class="math display">\[dp_{i, j} = \min(dp_{i - 1, j - v_i} + w_i)\]</span></p><p>然后我们就可以判断如果 <span class="math inline">\(dp_{i, j} \leW\)</span>,我们就统计答案。</p><p>本体依然可以降维优化,这里不在赘述。</p><p>时间复杂度:<span class="math inline">\(\mathcal O (n \times10^5)\)</span>。</p><h2 id="代码">代码</h2><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></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">define</span> int long long</span></span><br><span class="line"></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> N = <span class="number">1e5</span> + <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m, w[N], v[N], dp[N], ans;</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="keyword">sizeof</span> dp);</span><br><span class="line"> cin >> n >> m;</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"> cin >> w[i] >> v[i];</span><br><span class="line"> }</span><br><span class="line"> dp[<span class="number">0</span>] = <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; i++) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1e5</span>; j >= v[i]; j--) {</span><br><span class="line"> dp[j] = <span class="built_in">min</span>(dp[j], dp[j - v[i]] + w[i]);</span><br><span class="line"> <span class="keyword">if</span> (dp[j] <= m) {</span><br><span class="line"> ans = <span class="built_in">max</span>(ans, j);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> cout << 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>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 动态规划dp </tag>
</tags>
</entry>
<entry>
<title>DP D 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20D%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20D%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>给定 <span class="math inline">\(n\)</span> 个物品,容量为 <spanclass="math inline">\(m\)</span>的背包,每个物品有一个价值和体积,数量只有一个,你需要求出取这些物品<span class="math inline">\(\sum_{i = 1}^{n} w_i \le W\)</span>的前提下最大化 <span class="math inline">\(\sum v_i\)</span>。</p><h2 id="思路">思路</h2><p>定义状态: <span class="math inline">\(dp_{i, j}\)</span> 表示前<span class="math inline">\(i\)</span> 个物品选择 <spanclass="math inline">\(j\)</span> 个物品的最大价值。</p><p>状态转移方程: <span class="math display">\[dp_{i, j} = \max(dp_{i - 1, j - w_i} + v_i)\]</span> 答案为 <span class="math inline">\(dp_{n, m}\)</span></p><p>时间复杂度:<span class="math inline">\(\mathcal O (n \timesm)\)</span>。</p><p>空间复杂度:<span class="math inline">\(\mathcal O (n \timesm)\)</span>。</p><h2 id="优化">优化</h2><p>由于状态转移方程转移只跟前一项有关,所以我们可以优化掉第一维,但我们就需要倒序循环,如果正序的话会导致物品选重复。</p><p>空间复杂度:<span class="math inline">\(\mathcal O (m)\)</span>。</p><h2 id="代码">代码</h2><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></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><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> N = <span class="number">110</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">long</span> <span class="type">long</span> n, m, w[N], v[N], dp[<span class="number">100010</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"> cin >> n >> m;</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"> cin >> w[i] >> v[i];</span><br><span class="line"> }</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">for</span>(<span class="type">int</span> j = m;j >= w[i];j--){</span><br><span class="line"> dp[j] = <span class="built_in">max</span>(dp[j - w[i]] + v[i], dp[j]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> cout << dp[m];</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>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 动态规划dp </tag>
<tag> 背包 </tag>
</tags>
</entry>
<entry>
<title>DP C 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20C%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20C%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>你有 <span class="math inline">\(N\)</span>天时间,每一天,你可以游泳、抓虫、做作业,你分别可以获得 <spanclass="math inline">\(a_i, b_i, c_i\)</span>点快乐值,你不能两天做一样的事情,请你求出这 <spanclass="math inline">\(N\)</span> 天的最大快乐值。 ## 思路</p><p>定义状态: <span class="math inline">\(dp_{i, j}\)</span> 表示第<span class="math inline">\(i\)</span> 天,选择第 <spanclass="math inline">\(j\)</span> 项活动获得的最大快乐价值。</p><p>状态转移方程: <span class="math display">\[\begin{equation}\begin{aligned}dp_{i, 1} = \max(dp_{i - 1, 2}, dp_{i - 1, 3}) + a_i \\dp_{i, 2} = \max(dp_{i - 1, 1}, dp_{i - 1, 3}) + b_i \\dp_{i, 3} = \max(dp_{i - 1, 2}, dp_{i - 1, 3}) + c_i\end{aligned}\end{equation}\]</span></p><p>答案为: <span class="math inline">\(dp_n\)</span>。</p><p>时间复杂度为:<span class="math inline">\(\mathcal O(n)\)</span>。</p><h2 id="代码">代码</h2><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="meta">#<span class="keyword">include</span> <span class="string"><bits/stdc++.h></span></span></span><br><span class="line"></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> N = <span class="number">1e5</span> + <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, dp[N][<span class="number">4</span>], a[N], b[N], c[N];</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"> cin >> 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"> cin >> a[i] >> b[i] >> c[i];</span><br><span class="line"> dp[<span class="number">1</span>][<span class="number">1</span>] = a[<span class="number">1</span>];</span><br><span class="line"> dp[<span class="number">1</span>][<span class="number">2</span>] = b[<span class="number">1</span>];</span><br><span class="line"> dp[<span class="number">1</span>][<span class="number">3</span>] = c[<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 <= n; i++) {</span><br><span class="line"> dp[i][<span class="number">1</span>] = <span class="built_in">max</span>(dp[i - <span class="number">1</span>][<span class="number">2</span>], dp[i - <span class="number">1</span>][<span class="number">3</span>]) + a[i];</span><br><span class="line"> dp[i][<span class="number">2</span>] = <span class="built_in">max</span>(dp[i - <span class="number">1</span>][<span class="number">1</span>], dp[i - <span class="number">1</span>][<span class="number">3</span>]) + b[i];</span><br><span class="line"> dp[i][<span class="number">3</span>] = <span class="built_in">max</span>(dp[i - <span class="number">1</span>][<span class="number">2</span>], dp[i - <span class="number">1</span>][<span class="number">1</span>]) + c[i];</span><br><span class="line"> }</span><br><span class="line"> cout << <span class="built_in">max</span>(dp[n][<span class="number">1</span>], <span class="built_in">max</span>(dp[n][<span class="number">2</span>], dp[n][<span class="number">3</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>]]></content>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 动态规划dp </tag>
<tag> 线性dp </tag>
</tags>
</entry>
<entry>
<title>DP B 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20B%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20B%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>你有 <span class="math inline">\(n\)</span> 个石头,你最多能跳 <spanclass="math inline">\(k\)</span> 个石头,你从第 <spanclass="math inline">\(i\)</span> 个石头跳到第 <spanclass="math inline">\(j\)</span> 个石头需要付出代价 <spanclass="math inline">\(|a_i - a_j|\)</span>,你需要求出从 <spanclass="math inline">\(1\)</span> 号石头跳到 <spanclass="math inline">\(n\)</span> 号石头最少需要付出的代价。</p><h2 id="思路">思路</h2><p>定义状态为 <span class="math inline">\(dp_i\)</span> 表示跳到第 <spanclass="math inline">\(i\)</span> 个石头需要付出的最小代价。</p><p>状态转移方程: <span class="math display">\[dp_i = \min(dp_{i - j} + |a_i - a_j|)\]</span></p><p>答案为:<span class="math inline">\(dp_n\)</span></p><p>时间复杂度:<span class="math inline">\(\mathcal O (n)\)</span>。</p><h2 id="代码">代码</h2><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="meta">#<span class="keyword">include</span> <span class="string"><bits/stdc++.h></span></span></span><br><span class="line"></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> N = <span class="number">1e5</span> + <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, k, a[N], dp[N];</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"> cin >> n >> k;</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"> cin >> a[i];</span><br><span class="line"> dp[i] = INT_MAX;</span><br><span class="line"> }</span><br><span class="line"> dp[<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> i = <span class="number">2</span>; i <= n; i++)</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j <= k; j++)</span><br><span class="line"> <span class="keyword">if</span> (i - j >= <span class="number">1</span>)</span><br><span class="line"> dp[i] = <span class="built_in">min</span>(dp[i], dp[i - j] + <span class="built_in">abs</span>(a[i] - a[i - j]));</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> cout << 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>]]></content>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 动态规划dp </tag>
<tag> 线性dp </tag>
</tags>
</entry>
<entry>
<title>DP a 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20A%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/DP%20A%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>给定 <span class="math inline">\(n\)</span>个石头,你每次可以跳到石头 <span class="math inline">\(i + 1\)</span> 和<span class="math inline">\(i+2\)</span> 上,你需要花费代价 <spanclass="math inline">\(|h_i - h_j|\)</span>(<spanclass="math inline">\(i\)</span> 表示当前所在的石头,<spanclass="math inline">\(j\)</span> 表示即将要跳到的石头),你需要求出从<span class="math inline">\(1\)</span> 号石头跳到 <spanclass="math inline">\(n\)</span> 号石头最小要付出的代价。</p><h2 id="思路">思路</h2><p>定义状态:<span class="math inline">\(dp_i\)</span> 表示跳到第 <spanclass="math inline">\(i\)</span> 个石头要付出的最小代价。</p><p>状态转移方程: <span class="math display">\[dp_i = \min(dp_{i - 1} + |a_i - a_{i - 1}|, dp_{i - 2} + |a_i - a_{i -2}|)\]</span></p><p>答案为 <span class="math inline">\(dp_n\)</span>。</p><p>时间复杂度:<span class="math inline">\(\mathcal O (n)\)</span>。 ##代码</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></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> N = <span class="number">1e5</span> + <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">long</span> <span class="type">long</span> n, a[N], dp[N];</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"> cin >> 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"> cin >> a[i];</span><br><span class="line"> dp[<span class="number">2</span>] = <span class="built_in">abs</span>(a[<span class="number">2</span>] - a[<span class="number">1</span>]);</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">3</span>; i <= n; i++) {</span><br><span class="line"> dp[i] = <span class="built_in">min</span>(dp[i - <span class="number">1</span>] + <span class="built_in">abs</span>(a[i] - a[i - <span class="number">1</span>]), dp[i - <span class="number">2</span>] + <span class="built_in">abs</span>(a[i] - a[i - <span class="number">2</span>]));</span><br><span class="line"> }</span><br><span class="line"> cout << 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>]]></content>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 动态规划dp </tag>
<tag> 线性dp </tag>
</tags>
</entry>
<entry>
<title>ABC373 D 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/ABC373%20D%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/ABC373%20D%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>你有 <span class="math inline">\(n\)</span> 个点,<spanclass="math inline">\(m\)</span> 条边,每条边有一个权值 <spanclass="math inline">\(w_i\)</span>,每条边要满足 <spanclass="math inline">\(x_{v_j} - x_{u_j} = w_j\)</span>,你需要求出数组<spanclass="math inline">\(x\)</span>,你可以输出任何一种满足条件的情况。 ##思路</p><p>这道题一开始还想到了用 spfa 写一个查分约束,结果直接 T 飞。</p><p>这道题由于保证绝对有解,并且这道题是等于号,所以他的变坏变好的程度是一样的,所以我们就可以使用BFS 来做。 ## 代码</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></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><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">using</span> ll = <span class="type">long</span> <span class="type">long</span>;</span><br><span class="line"><span class="keyword">using</span> pii = pair<ll, ll>;</span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">2e5</span> + <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m;</span><br><span class="line"><span class="type">bool</span> vis[N];</span><br><span class="line">ll dis[N];</span><br><span class="line">vector<pii> e[N];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">bfs</span><span class="params">(<span class="type">int</span> s)</span> </span>{</span><br><span class="line"> queue<<span class="type">int</span>> q;</span><br><span class="line"> q.<span class="built_in">push</span>(s);</span><br><span class="line"> <span class="keyword">while</span> (!q.<span class="built_in">empty</span>()) {</span><br><span class="line"> <span class="type">int</span> u = q.<span class="built_in">front</span>();</span><br><span class="line"> q.<span class="built_in">pop</span>();</span><br><span class="line"> vis[u] = <span class="literal">true</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">auto</span> [v, w] : e[u]) {</span><br><span class="line"> <span class="keyword">if</span> (!vis[v]) {</span><br><span class="line"> dis[v] = dis[u] + w;</span><br><span class="line"> q.<span class="built_in">push</span>(v);</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><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"> cin >> n >> m;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i <= m; i++) {</span><br><span class="line"> ll u, v, w;</span><br><span class="line"> cin >> u >> v >> w;</span><br><span class="line"> e[u].<span class="built_in">push_back</span>({v, w});</span><br><span class="line"> e[v].<span class="built_in">push_back</span>({u, -w});</span><br><span class="line"> }</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> (!vis[i]) {</span><br><span class="line"> <span class="built_in">bfs</span>(i);</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">1</span>; i <= n; i++) {</span><br><span class="line"> cout << dis[i] << <span class="string">" "</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>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 图论 </tag>
<tag> BFS </tag>
</tags>
</entry>
<entry>
<title>ABC373 C 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/ABC373%20C%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/ABC373%20C%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>给定一个长度为 <span class="math inline">\(n\)</span> 的数组 <spanclass="math inline">\(A\)</span> 和 <spanclass="math inline">\(B\)</span>,你需要求出最大的 <spanclass="math inline">\(A_i + B_j\)</span>。 ## 思路</p><p>要最大肯定是求数组 <span class="math inline">\(A\)</span> 和 <spanclass="math inline">\(B\)</span> 中元素的最大值,然后没了。 ## 代码</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="meta">#<span class="keyword">include</span><span class="string"><bits/stdc++.h></span></span></span><br><span class="line"></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">int</span> n, a[<span class="number">500010</span>], b[<span class="number">500010</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"> cin >> 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++) cin >> a[i];</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j <= n; j++) cin >> b[i];</span><br><span class="line"> cout << *<span class="built_in">max_element</span>(a + <span class="number">1</span>, a + n + <span class="number">1</span>) + *<span class="built_in">max_element</span>(b + <span class="number">1</span>, b + 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>]]></content>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 贪心 </tag>
<tag> 题解 </tag>
</tags>
</entry>
<entry>
<title>ABC373 B 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/ABC373%20B%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/ABC373%20B%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<p>挺坑的,题目有点没有讲清楚。大概意思是你需要按照<code>ABCDEFGHIJKLMNOPQRSTUVWXYZ</code>的顺序输入字符。我们直接哪一个数组记录每个字母出现的位置就可以了。</p><h2 id="代码">代码</h2><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></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><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="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> ans = <span class="number">0</span>, a[<span class="number">30</span>];</span><br><span class="line"> string s;</span><br><span class="line"> cin >> s;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < s.<span class="built_in">size</span>(); i++) </span><br><span class="line"> a[s[i] - <span class="string">'A'</span>] = i;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < s.<span class="built_in">size</span>() - <span class="number">1</span>; i++) </span><br><span class="line"> ans += <span class="built_in">abs</span>(a[i] - a[i + <span class="number">1</span>]);</span><br><span class="line"> cout << 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>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
</tags>
</entry>
<entry>
<title>ABC373 a 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/ABC373%20A%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/ABC373%20A%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<p>直接使用 c++ 中的 <code>string</code> 中的 <code>size</code>函数,直接判断。</p><h2 id="代码">代码</h2><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="meta">#<span class="keyword">include</span><span class="string"><bits/stdc++.h></span></span></span><br><span class="line"></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="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> 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 <= <span class="number">12</span>; i++) {</span><br><span class="line"> string s;</span><br><span class="line"> cin >> s;</span><br><span class="line"> <span class="keyword">if</span> (s.<span class="built_in">size</span>() == i) {</span><br><span class="line"> ans++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> cout << ans << endl;</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>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 字符串 </tag>
</tags>
</entry>
<entry>
<title>ABC369 E 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/ABC369%20E%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/ABC369%20E%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<p>原题链接:<ahref="https://atcoder.jp/contests/abc369/tasks/abc369_e">abc369_e</a>。</p><h2 id="题意">题意</h2><p>给定一张图,有 <span class="math inline">\(n\)</span> 个点,<spanclass="math inline">\(m\)</span> 条边,每个边有他的边权。现在给定 <spanclass="math inline">\(q\)</span> 次询问,会给定 <spanclass="math inline">\(k\)</span> 条边,要求你从节点 <spanclass="math inline">\(1\)</span> 走到节点 <spanclass="math inline">\(n\)</span> 必须经过这 <spanclass="math inline">\(k\)</span> 条边,请问最小代价是多少。</p><h2 id="思路">思路</h2><p>我们可以发现 <span class="math inline">\(n\)</span>的值都很小,所以,我们就可以直接跑Floyd,将每个点的最短路求出来。再看每一次的 <spanclass="math inline">\(k\)</span>也很小,所以我们就可以直接爆搜求最小值。</p><p>时间复杂度:<span class="math inline">\(\mathcal{O}(n^3 + q \times2^k)\)</span>。</p><h2 id="代码">代码</h2><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></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><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">using</span> ll = <span class="type">long</span> <span class="type">long</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">410</span>;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> M = <span class="number">2e5</span> + <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m, u[M], v[M], a[<span class="number">10</span>], x;</span><br><span class="line">ll dis[N][N], w[M], ans = <span class="number">1e18</span>; <span class="comment">// long long 注意</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> pre, <span class="type">int</span> k, ll sum)</span> </span>{ <span class="comment">// 爆搜</span></span><br><span class="line"> <span class="keyword">if</span> (k > x) {</span><br><span class="line"> sum += dis[pre][n];</span><br><span class="line"> ans = <span class="built_in">min</span>(ans, sum);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">dfs</span>(u[a[k]], k + <span class="number">1</span>, sum + dis[pre][v[a[k]]] + w[a[k]]);</span><br><span class="line"> <span class="built_in">dfs</span>(v[a[k]], k + <span class="number">1</span>, sum + dis[pre][u[a[k]]] + w[a[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"> cin >> n >> m;</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">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j <= n; j++)</span><br><span class="line"> dis[i][j] = <span class="number">1e12</span> * (i != j);</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i <= m; i++) {</span><br><span class="line"> cin >> u[i] >> v[i] >> w[i];</span><br><span class="line"> dis[u[i]][v[i]] = <span class="built_in">min</span>(dis[u[i]][v[i]], w[i]);</span><br><span class="line"> dis[v[i]][u[i]] = <span class="built_in">min</span>(dis[v[i]][u[i]], w[i]);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> k = <span class="number">1</span>; k <= n; k++) <span class="comment">// Floyd</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">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j <= n; j++) </span><br><span class="line"> dis[i][j] = <span class="built_in">min</span>(dis[i][j], dis[i][k] + dis[k][j]);</span><br><span class="line"> <span class="type">int</span> q;</span><br><span class="line"> cin >> q;</span><br><span class="line"> <span class="keyword">while</span> (q--) {</span><br><span class="line"> cin >> x;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i <= x; i++) {</span><br><span class="line"> cin >> a[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">sort</span>(a + <span class="number">1</span>, a + x + <span class="number">1</span>); <span class="comment">// 记得要排序</span></span><br><span class="line"> ll num = <span class="number">1e18</span>;</span><br><span class="line"> <span class="keyword">do</span> {</span><br><span class="line"> ans = <span class="number">1e18</span>;</span><br><span class="line"> <span class="built_in">dfs</span>(<span class="number">1</span>, <span class="number">1</span>, <span class="number">0</span>);</span><br><span class="line"> num = <span class="built_in">min</span>(num, ans);</span><br><span class="line"> } <span class="keyword">while</span> (<span class="built_in">next_permutation</span>(a + <span class="number">1</span>, a + x + <span class="number">1</span>));</span><br><span class="line"> cout << num << endl;</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>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 最短路 </tag>
<tag> Floyd </tag>
</tags>
</entry>
<entry>
<title>ABC243 E 题解</title>
<link href="/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/ABC243%20E%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/Atcoder%E9%A2%98%E8%A7%A3/ABC243%20E%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>给定一个 <span class="math inline">\(n\)</span> 个顶点 <spanclass="math inline">\(m\)</span>条边的无向简单图,你需要求出最大删除的边的数量,使得任意两个点 <spanclass="math inline">\(s\)</span>、<spanclass="math inline">\(t\)</span>,他们之间的最短距离不变。</p><h2 id="数据范围">数据范围</h2><ul><li><span class="math inline">\(2 \le N \le 300\)</span></li><li><span class="math inline">\(N - 1 \le M \le\frac{N(N-1)}{2}\)</span></li><li><span class="math inline">\(1 \le A_i \le B_i \le N\)</span></li><li><span class="math inline">\(C_i \le 10^9\)</span></li></ul><h2 id="思路">思路</h2><p>我们可以发现 <span class="math inline">\(N \le 300\)</span>,而题目要让删除的边对于任意两个点的最短距离都不变,所以我们可以跑一遍Floyd,将每两个点的最短距离给跑出来,然后判断每一条边,他是否影响 <spanclass="math inline">\(s\)</span> 到 <spanclass="math inline">\(t\)</span> 的最短路,如果不影响,我们就让答案加<span class="math inline">\(1\)</span>。最后要让答案除 <spanclass="math inline">\(2\)</span>,因为这是无向图,会重复计算。</p><p>这里还有个问题,如果按我们上面的方法,会出现负数情况,为什么呢?答案就是边数小于点数,这样的图会变成一棵树,任何一条边都不能删去。</p><h2 id="ac-code"><em>ac code</em></h2><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"><bits/stdc++.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">310</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m, ans;</span><br><span class="line"><span class="type">long</span> <span class="type">long</span> dis[N][N]; <span class="comment">// 记得开 long long</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"> cin >> n >> m;</span><br><span class="line"> <span class="keyword">if</span> (m < n) { <span class="comment">// 特判,如果边小于点数输出 0</span></span><br><span class="line"> cout << <span class="number">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="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i <= n; i++) { <span class="comment">// 初始化</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="keyword">if</span> (i != j) {</span><br><span class="line"> dis[i][j] = <span class="number">1e9</span>;</span><br><span class="line"> }</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">1</span>, x, y, z; i <= m; i++) {</span><br><span class="line"> cin >> x >> y >> z;</span><br><span class="line"> dis[x][y] = dis[y][x] = z;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> k = <span class="number">1</span>; k <= n; k++) { <span class="comment">// Floyd</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">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j <= n; j++) {</span><br><span class="line"> dis[i][j] = <span class="built_in">min</span>(dis[i][j], dis[i][k] + dis[k][j]);</span><br><span class="line"> }</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">1</span>; i <= n; i++) {</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 class="comment">// 枚举边</span></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><br><span class="line"> <span class="type">bool</span> f = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> k = <span class="number">1</span>; k <= n; k++) {</span><br><span class="line"> <span class="keyword">if</span> (i != k && j != k && dis[i][j] == dis[i][k] + dis[k][j]) {</span><br><span class="line"> f = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> } <span class="comment">// 如果发现两个点的与这个边有关,这个边就不能删去</span></span><br><span class="line"> }</span><br><span class="line"> ans += f;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> ans /= <span class="number">2</span>;</span><br><span class="line"> cout << m - 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>
<categories>
<category> Atcoder题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 图论 </tag>
<tag> 最短路 </tag>
</tags>
</entry>
<entry>
<title>P4513 题解</title>
<link href="/2024/10/25/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P4513%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P4513%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>你有一个长度为 <span class="math inline">\(n\)</span> 的序列,有<span class="math inline">\(m\)</span>次询问,每次询问有以下两种情况:</p><ol type="1"><li><span class="math inline">\(k = 1\)</span> 时,给定 <spanclass="math inline">\([l, r]\)</span>,你需要求出这个区间的最大字段和。> 什么是最大字段和? > > 给定一个区间 <spanclass="math inline">\([l, r]\)</span>,你需要求出 <spanclass="math inline">\(a_i + a_{i + 1} \dots a_j\)</span> 的最大值,<spanclass="math inline">\(l \le i \le j \le r\)</span>。</li><li><span class="math inline">\(k = 2\)</span> 时,给定 <spanclass="math inline">\(x, y\)</span>,表示将序列中的第 <spanclass="math inline">\(x\)</span> 位的数值改成 <spanclass="math inline">\(y\)</span>。</li></ol><h2 id="思路">思路</h2><p>很明显,这道题我们需要用线段树来维护。</p><p>首先,线段树里一定要维护一个答案。</p><p>我们在进行分类讨论:</p><ol type="1"><li>答案都在右边的时。答案就在右边的最大字段和里,可以直接调用。</li><li>答案都在坐边的时候。与上面一样。</li><li>答案的两边都有时。我们为了使这个值最大,我们肯定左右两边的最大前缀和和最大后缀和,但要维护这两个值,我们就需要一个求和答案。为什么呢,有一种情况就是这个区间的最大前缀和可能是左边的所有数值加起来在加上右边的最大后缀和。</li></ol><p>然后根据以上的结论就可以写出代码了。</p><h2 id="代码">代码</h2><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></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">define</span> ls(x) (x << 1) <span class="comment">// 左子树</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rs(x) (x << 1 | 1) <span class="comment">// 右子树</span></span></span><br><span class="line"></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> N = <span class="number">5e5</span> + <span class="number">10</span>; <span class="comment">// 定义数组的大小</span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m, a[N]; <span class="comment">// n为数组长度,m为操作次数,a为存储数据的数组</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">SegmentTree</span> { <span class="comment">// 段树结构体</span></span><br><span class="line"> <span class="type">int</span> lmax, rmax, ans, sum; <span class="comment">// 左最大值、右最大值、答案、总和</span></span><br><span class="line">} tree[N << <span class="number">2</span>]; <span class="comment">// 段树数组</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">pushup</span><span class="params">(<span class="type">int</span> rt)</span> </span>{ <span class="comment">// 更新父节点</span></span><br><span class="line"> tree[rt].lmax = <span class="built_in">max</span>(tree[<span class="built_in">ls</span>(rt)].lmax, tree[<span class="built_in">ls</span>(rt)].sum + tree[<span class="built_in">rs</span>(rt)].lmax); <span class="comment">// 更新左最大值</span></span><br><span class="line"> tree[rt].rmax = <span class="built_in">max</span>(tree[<span class="built_in">rs</span>(rt)].rmax, tree[<span class="built_in">rs</span>(rt)].sum + tree[<span class="built_in">ls</span>(rt)].rmax); <span class="comment">// 更新右最大值</span></span><br><span class="line"> tree[rt].sum = tree[<span class="built_in">ls</span>(rt)].sum + tree[<span class="built_in">rs</span>(rt)].sum; <span class="comment">// 更新总和</span></span><br><span class="line"> tree[rt].ans = <span class="built_in">max</span>({tree[<span class="built_in">ls</span>(rt)].ans, tree[<span class="built_in">rs</span>(rt)].ans, tree[<span class="built_in">ls</span>(rt)].rmax + tree[<span class="built_in">rs</span>(rt)].lmax}); <span class="comment">// 更新答案</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">build</span><span class="params">(<span class="type">int</span> l, <span class="type">int</span> r, <span class="type">int</span> rt)</span> </span>{ <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"> tree[rt].lmax = tree[rt].rmax = tree[rt].ans = tree[rt].sum = 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 class="comment">// 计算中间位置</span></span><br><span class="line"> <span class="built_in">build</span>(l, mid, <span class="built_in">ls</span>(rt)); <span class="comment">// 构建左子树</span></span><br><span class="line"> <span class="built_in">build</span>(mid + <span class="number">1</span>, r, <span class="built_in">rs</span>(rt)); <span class="comment">// 构建右子树</span></span><br><span class="line"> <span class="built_in">pushup</span>(rt); <span class="comment">// 更新父节点</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">updata</span><span class="params">(<span class="type">int</span> l, <span class="type">int</span> r, <span class="type">int</span> rt, <span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <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"> <span class="keyword">if</span> (l == x)</span><br><span class="line"> tree[rt].lmax = tree[rt].rmax = tree[rt].ans = tree[rt].sum = y; <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 class="comment">// 计算中间位置</span></span><br><span class="line"> <span class="keyword">if</span> (x <= mid)</span><br><span class="line"> <span class="built_in">updata</span>(l, mid, <span class="built_in">ls</span>(rt), x, y); <span class="comment">// 更新左子树</span></span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> <span class="built_in">updata</span>(mid + <span class="number">1</span>, r, <span class="built_in">rs</span>(rt), x, y); <span class="comment">// 更新右子树</span></span><br><span class="line"> <span class="built_in">pushup</span>(rt); <span class="comment">// 更新父节点</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function">SegmentTree <span class="title">query</span><span class="params">(<span class="type">int</span> l, <span class="type">int</span> r, <span class="type">int</span> rt, <span class="type">int</span> x, <span class="type">int</span> y)</span> </span>{ <span class="comment">// 查询区间</span></span><br><span class="line"> <span class="keyword">if</span> (l >= x && r <= y) { <span class="comment">// 完全包含</span></span><br><span class="line"> <span class="keyword">return</span> tree[rt]; <span class="comment">// 返回当前节点</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 class="comment">// 计算中间位置</span></span><br><span class="line"> <span class="keyword">if</span> (y <= mid) <span class="keyword">return</span> <span class="built_in">query</span>(l, mid, <span class="built_in">ls</span>(rt), x, y); <span class="comment">// 查询左子树</span></span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">if</span> (x > mid) <span class="keyword">return</span> <span class="built_in">query</span>(mid + <span class="number">1</span>, r, <span class="built_in">rs</span>(rt), x, y); <span class="comment">// 查询右子树</span></span><br><span class="line"> <span class="keyword">else</span> { <span class="comment">// 分别查询左右子树</span></span><br><span class="line"> SegmentTree ltree = <span class="built_in">query</span>(l, mid, <span class="built_in">ls</span>(rt), x, y);</span><br><span class="line"> SegmentTree rtree = <span class="built_in">query</span>(mid + <span class="number">1</span>, r, <span class="built_in">rs</span>(rt), x, y);</span><br><span class="line"> SegmentTree res; <span class="comment">// 合并结果</span></span><br><span class="line"> res.lmax = <span class="built_in">max</span>(ltree.lmax, ltree.sum + rtree.lmax);</span><br><span class="line"> res.rmax = <span class="built_in">max</span>(rtree.rmax, rtree.sum + ltree.rmax);</span><br><span class="line"> res.sum = ltree.sum + rtree.sum;</span><br><span class="line"> res.ans = <span class="built_in">max</span>({ltree.ans, rtree.ans, ltree.rmax + rtree.lmax});</span><br><span class="line"> <span class="keyword">return</span> res; <span class="comment">// 返回合并结果</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">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> ios::<span class="built_in">sync_with_stdio</span>(<span class="literal">false</span>); <span class="comment">// 加速输入输出</span></span><br><span class="line"> cin.<span class="built_in">tie</span>(<span class="number">0</span>); <span class="comment">// 解除cin和cout的绑定</span></span><br><span class="line"> cin >> n >> m; <span class="comment">// 输入n和m</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"> cin >> a[i]; <span class="comment">// 输入数组元素</span></span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">build</span>(<span class="number">1</span>, n, <span class="number">1</span>); <span class="comment">// 构建段树</span></span><br><span class="line"> <span class="keyword">while</span> (m--) { <span class="comment">// 处理m个操作</span></span><br><span class="line"> <span class="type">int</span> op, x, y;</span><br><span class="line"> cin >> op >> x >> y; <span class="comment">// 输入操作类型和参数</span></span><br><span class="line"> <span class="keyword">if</span> (op == <span class="number">1</span>) { <span class="comment">// 查询操作</span></span><br><span class="line"> <span class="keyword">if</span> (x > y) <span class="built_in">swap</span>(x, y); <span class="comment">// 确保x小于等于y</span></span><br><span class="line"> cout << <span class="built_in">query</span>(<span class="number">1</span>, n, <span class="number">1</span>, x, y).ans << <span class="string">'\n'</span>; <span class="comment">// 输出查询结果</span></span><br><span class="line"> } <span class="keyword">else</span> { <span class="comment">// 更新操作</span></span><br><span class="line"> <span class="built_in">updata</span>(<span class="number">1</span>, n, <span class="number">1</span>, x, y); <span class="comment">// 更新值</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 class="comment">// 程序结束</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 洛谷题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 线段树 </tag>
</tags>
</entry>
<entry>
<title>P1005 题解</title>
<link href="/2024/10/25/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P1005%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/25/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P1005%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>对于一个给定的 <span class="math inline">\(n \times m\)</span>的矩阵,矩阵中的每个元素 <span class="math inline">\(a_{i,j}\)</span>均为非负整数。游戏规则如下:</p><ol type="1"><li>每次取数时须从每行各取走一个元素,共 <spanclass="math inline">\(n\)</span> 个。经过 <spanclass="math inline">\(m\)</span> 次后取完矩阵内所有元素;</li><li>每次取走的各个元素只能是该元素所在行的行首或行尾;</li><li>每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 =被取走的元素值 <span class="math inline">\(\times 2^i\)</span>,其中<span class="math inline">\(i\)</span> 表示第 <spanclass="math inline">\(i\)</span> 次取数(从 <spanclass="math inline">\(1\)</span> 开始编号);</li><li>游戏结束总得分为 <span class="math inline">\(m\)</span>次取数得分之和。</li></ol><p>对于任意矩阵,你需要求出取数后的最大得分。</p><h2 id="思路">思路</h2><p>我们会发现,每一行的结果不会对其他行产生影响,所以我们就可以针对于每一行进行区间dp。</p><p>我们设 <span class="math inline">\(dp_{i, j}\)</span> 表示将区间<span class="math inline">\([i, j]\)</span> 取完后的最大值。</p><p>转移为: <span class="math display">\[dp_{i, j} = \max(dp_{i - 1, j} + 2^{m - j + i} \times a_{i - 1}, dp_{i,j + 1} + 2^{m - j + i} \times a_{j + 1})\]</span></p><p>答案就是 <span class="math inline">\(\sum^{n}_{i = 1} \max_{j =1}^{m} dp_{i, i} + a_i \times 2^m\)</span>。</p><blockquote><p>注意:</p><p>这道题需要 <code>__int128_t</code>。</p></blockquote><h2 id="代码">代码</h2><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></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><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> N = <span class="number">100</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m;</span><br><span class="line"><span class="type">__int128_t</span> a[N], dp[N][N], ans, p[N];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">read</span><span class="params">(<span class="type">__int128_t</span> &x)</span> </span>{</span><br><span class="line"> x = <span class="number">0</span>;</span><br><span class="line"> <span class="type">int</span> f = <span class="number">1</span>;</span><br><span class="line"> <span class="type">char</span> ch = <span class="built_in">getchar</span>();</span><br><span class="line"> <span class="keyword">while</span> (ch < <span class="string">'0'</span> || ch > <span class="string">'9'</span>) {</span><br><span class="line"> <span class="keyword">if</span> (ch == <span class="string">'-'</span>) f = <span class="number">-1</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> (ch >= <span class="string">'0'</span> && ch <= <span class="string">'9'</span>) {</span><br><span class="line"> x = x * <span class="number">10</span> + ch - <span class="string">'0'</span>;</span><br><span class="line"> ch = <span class="built_in">getchar</span>();</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">void</span> <span class="title">print</span><span class="params">(<span class="type">__int128_t</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">print</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">__int128_t</span> <span class="title">solve</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">memset</span>(dp, <span class="number">0</span>, <span class="built_in">sizeof</span>(dp));</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i <= m; i++) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> j = m; j >= i; j--) {</span><br><span class="line"> dp[i][j] = <span class="built_in">max</span>(dp[i - <span class="number">1</span>][j] + p[m - j + i - <span class="number">1</span>] * a[i - <span class="number">1</span>], dp[i][j + <span class="number">1</span>] + p[m - j + i - <span class="number">1</span>] * a[j + <span class="number">1</span>]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="type">__int128_t</span> res = <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 <= m; i++) {</span><br><span class="line"> res = <span class="built_in">max</span>(res, dp[i][i] + p[m] * a[i]);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> res;</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"> p[<span class="number">0</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">1</span>; i <= <span class="number">90</span>; i++) p[i] = p[i - <span class="number">1</span>] * <span class="number">2</span>;</span><br><span class="line"> cin >> n >> m;</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">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j <= m; j++) {</span><br><span class="line"> <span class="built_in">read</span>(a[j]);</span><br><span class="line"> }</span><br><span class="line"> ans += <span class="built_in">solve</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (ans == <span class="number">0</span>) <span class="built_in">printf</span>(<span class="string">"0"</span>);</span><br><span class="line"> <span class="keyword">else</span> <span class="built_in">print</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>
<categories>
<category> 洛谷题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 区间dp </tag>
<tag> 动态规划dp </tag>
</tags>
</entry>
<entry>
<title>P9847 题解</title>
<link href="/2024/10/23/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P9847%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/23/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P9847%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="翻译">翻译</h2><p>洛谷的翻译不好,先提供个翻译</p><h3 id="题目描述">题目描述</h3><p>派蒙正在一棵树上捉晶蝇,这些晶蝇是提瓦特特有的一种蝴蝶。这棵树是一个由<span class="math inline">\(n\)</span> 个顶点和 <spanclass="math inline">\((n - 1)\)</span> 条无向边组成的连通图。</p><p>初始时有 <span class="math inline">\(a_i\)</span> 只晶蝇在第 <spanclass="math inline">\(i\)</span>个顶点上。当派蒙到达一个顶点时,她可以立即捉住该顶点上剩余的所有晶蝇。然而,晶蝇很胆小。当派蒙到达一个顶点时,相邻顶点上的晶蝇会被惊动。对于第<span class="math inline">\(i\)</span> 个顶点,如果该顶点上的晶蝇在第<span class="math inline">\(t'\)</span>秒开始时第一次被惊动,它们将在第 <span class="math inline">\((t' +t_{i})\)</span> 秒结束时消失。</p><p>在第 <span class="math inline">\(0\)</span> 秒开始时,派蒙到达顶点<span class="math inline">\(1\)</span> 并在第 <spanclass="math inline">\(1\)</span>秒开始前停留在那里。然后在接下来的每一秒开始时,她可以选择以下两种操作之一:-移动到当前顶点的一个相邻顶点并在下一秒开始前停留在那里(如果目的地的晶蝇将在那一秒结束时消失,她仍然可以捉住它们)。- 在当前顶点停留不动,直到下一秒开始前。</p><p>计算在 <span class="math inline">\(10^{10^{10^{10^{10}}}}\)</span>秒内派蒙最多可以捉到多少只晶蝇。</p><h3 id="输入">输入</h3><p>有多个测试用例。输入的第一行包含一个整数 <spanclass="math inline">\(T\)</span>,表示测试用例的数量。对于每个测试用例:</p><p>第一行包含一个整数 <span class="math inline">\(n\)</span>(<spanclass="math inline">\(1 \le n \le 10^5\)</span>),表示顶点的数量。</p><p>第二行包含 <span class="math inline">\(n\)</span> 个整数 <spanclass="math inline">\(a_1, a_2, \cdots, a_n\)</span>(<spanclass="math inline">\(1 \le a_i \le 10^9\)</span>),其中 <spanclass="math inline">\(a_i\)</span> 表示第 <spanclass="math inline">\(i\)</span> 个顶点上的晶蝇数量。</p><p>第三行包含<span class="math inline">\(n\)</span>个整数 <spanclass="math inline">\(t_1, t_2, \cdots, t_n\)</span>(<spanclass="math inline">\(1 \le t_i \le 3\)</span> ),其中 <spanclass="math inline">\(t_i\)</span> 表示第 <spanclass="math inline">\(i\)</span>个顶点上的晶蝇在被惊动后消失前的时间。</p><p>接下来的 <span class="math inline">\((n - 1)\)</span> 行,第<spanclass="math inline">\(i\)</span>行包含两个整数 <spanclass="math inline">\(u_i\)</span> 和 <spanclass="math inline">\(v_i\)</span>( <span class="math inline">\(1 \leu_i, v_i \le n\)</span> ),表示树中连接顶点 <spanclass="math inline">\(u_i\)</span> 和 <spanclass="math inline">\(v_i\)</span> 的一条边。</p><p>保证所有测试用例的 <span class="math inline">\(n\)</span>的总和不超过 <span class="math inline">\(10^6\)</span> 。</p><h2 id="分析">分析</h2><p>看到这道题目,我们首先不要想 <span class="math inline">\(dp\)</span>怎么写,先想想搜索应该怎么写。</p><p>写搜索时,我们的第一反应就是枚举情况。我们就会想到有三种情况:</p><ul><li><p>自己这个点上的金蝶不在了,子节点的金蝶也不在了</p></li><li><p>自己这个点上的金蝶不在了,子节点上的金蝶还在</p></li><li><p>自己这个点上的金蝶在,子节点上的金蝶也在</p></li></ul><p>然而我们发现,第三种情况就是第二种情况再加上自己的节点上的金蝶数,所以我们可以不用考虑第三种情况。</p><p>然后,我们还要考虑一个问题,就是在一个子节点上抓完金蝶,然后再去另一个子节点上抓,然而可以达成这种情况只有一种可能,那就时<span class="math inline">\(t = 3\)</span> 的时候,所以我们还要开一个<code>vector</code> (或链式前向星)来存储这种特殊情况。</p><p>其实写道这里,我们的 <span class="math inline">\(dp\)</span>大致就可以写出来了。</p><h3 id="定义状态">定义状态</h3><p><span class="math inline">\(dp_{i, 0/1}\)</span> 表示自己这个点上的金蝶不在了,子节点的金蝶也不在(或在)的情况所最多能抓到多少只金蝶。</p><h3 id="状态转移方程">状态转移方程</h3><ul><li>初始状态:</li></ul><p><span class="math inline">\(dp_{i, 0} = \sum_{v \inson_u}\)</span></p><p><span class="math inline">\(dp_{i, 1} = \sum_{v \in son_u} +\max(val_v)\)</span></p><ul><li>如果存在 <span class="math inline">\(t = 3\)</span>的情况(<code>!g.empty()</code>)</li></ul><ol type="1"><li><span class="math inline">\(v = maxid1\)</span></li></ol><p><span class="math inline">\(dp_{u, 1} = \max(val_v + dp_{v, 0} +\sum_{v \in son_u} - dp_{v, 1} + max2)\)</span></p><ol start="2" type="1"><li><span class="math inline">\(v \not= maxid1\)</span></li></ol><p><span class="math inline">\(dp_{u, 1} = \max(val_v + dp_{v , 0} +\sum_{v \in son_u} - dp_{v, 1} + max1)\)</span></p><p>解释一下,<span class="math inline">\(max1\)</span> 是最大值,<spanclass="math inline">\(max2\)</span> 是次大值,<spanclass="math inline">\(maxid1\)</span> 和 <spanclass="math inline">\(maxid2\)</span> 是最大值和次大值的节点编号。</p><h2 id="ac-code"><em>AC Code</em></h2><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"><bits/stdc++.h></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 class="type">const</span> <span class="type">int</span> N = <span class="number">1e5</span> + <span class="number">10</span>;</span><br><span class="line"><span class="type">int</span> q, n, val[N], t[N], x, y, dp[N][<span class="number">2</span>];</span><br><span class="line">vector<<span class="type">int</span>> e[N], g[N];</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> sum = <span class="number">0</span>, maxi = <span class="number">0</span>;</span><br><span class="line"> dp[u][<span class="number">1</span>] = dp[u][<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">auto</span> v : e[u]){</span><br><span class="line"> <span class="keyword">if</span>(v == fa)</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> <span class="built_in">dfs</span>(v, u);</span><br><span class="line"> sum += dp[v][<span class="number">1</span>];</span><br><span class="line"> maxi = <span class="built_in">max</span>(maxi, val[v]);</span><br><span class="line"> }</span><br><span class="line"> dp[u][<span class="number">0</span>] = sum;</span><br><span class="line"> dp[u][<span class="number">1</span>] = sum + maxi;</span><br><span class="line"> <span class="keyword">if</span>(g[u].<span class="built_in">size</span>()){</span><br><span class="line"> <span class="type">int</span> maxi1 = <span class="number">-1e18</span>, maxi2 = <span class="number">-1e18</span>, maxid1 = <span class="number">0</span>, maxid2 = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">auto</span> v : g[u]){</span><br><span class="line"> <span class="keyword">if</span>(v == fa)</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> <span class="keyword">if</span>(maxi1 < val[v]){</span><br><span class="line"> maxi2 = maxi1;</span><br><span class="line"> maxid2 = maxid1;</span><br><span class="line"> maxi1 = val[v];</span><br><span class="line"> maxid1 = v;</span><br><span class="line"> }<span class="keyword">else</span> <span class="keyword">if</span>(maxi2 < val[v]){</span><br><span class="line"> maxi2 = val[v];</span><br><span class="line"> maxid2 = v;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="type">int</span> maxx = <span class="number">-2e18</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">auto</span> v : e[u]){</span><br><span class="line"> <span class="keyword">if</span>(v == fa)</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> <span class="keyword">if</span>(v == maxid1){</span><br><span class="line"> maxx = <span class="built_in">max</span>(maxx, val[v] + dp[v][<span class="number">0</span>] + sum - dp[v][<span class="number">1</span>] + maxi2);</span><br><span class="line"> }<span class="keyword">else</span></span><br><span class="line"> maxx = <span class="built_in">max</span>(maxx, val[v] + dp[v][<span class="number">0</span>] + sum - dp[v][<span class="number">1</span>] + maxi1);</span><br><span class="line"> }</span><br><span class="line"> dp[u][<span class="number">1</span>] = <span class="built_in">max</span>(dp[u][<span class="number">1</span>], maxx);</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"> ios::<span class="built_in">sync_with_stdio</span>(<span class="literal">false</span>);</span><br><span class="line"> cin.<span class="built_in">tie</span>(<span class="number">0</span>);</span><br><span class="line"> cout.<span class="built_in">tie</span>(<span class="number">0</span>);</span><br><span class="line"> cin >> q;</span><br><span class="line"> <span class="keyword">while</span>(q--){</span><br><span class="line"> cin >> 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"> cin >> val[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++)</span><br><span class="line"> cin >> t[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++){</span><br><span class="line"> cin >> x >> y;</span><br><span class="line"> e[x].<span class="built_in">push_back</span>(y);</span><br><span class="line"> e[y].<span class="built_in">push_back</span>(x);</span><br><span class="line"> <span class="keyword">if</span>(t[x] == <span class="number">3</span>)</span><br><span class="line"> g[y].<span class="built_in">push_back</span>(x);</span><br><span class="line"> <span class="keyword">if</span>(t[y] == <span class="number">3</span>)</span><br><span class="line"> g[x].<span class="built_in">push_back</span>(y);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">dfs</span>(<span class="number">1</span>, <span class="number">-1</span>);</span><br><span class="line"> cout << dp[<span class="number">1</span>][<span class="number">1</span>] + val[<span class="number">1</span>] << <span class="string">'\n'</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"> e[i].<span class="built_in">clear</span>();</span><br><span class="line"> g[i].<span class="built_in">clear</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>]]></content>
<categories>
<category> 洛谷题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 动态规划dp </tag>
<tag> 树形dp </tag>
</tags>
</entry>
<entry>
<title>P8637 题解</title>
<link href="/2024/10/23/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P8637%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/23/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P8637%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<p>emm...说句实话,这道题真的很水,本以为很难,一看数据范围,直接暴力枚举!(差点打废了)</p><p><a href="https://www.luogu.com.cn/problem/P8637">题目传送门</a></p><h3 id="思路">思路:</h3><p>我们用两个for循环判断,第一个for循环来判断哪一个数据还没有到达指定位置,第二个for循环经行判断这个位置的正确数据在哪个位置上,由于题目给出数据绝对是<spanclass="math inline">\(1 \simN\)</span>,所以,我们不用担心缺序的情况(不然难度飙升)。</p><h3 id="代码">代码:</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></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 class="type">int</span> a[<span class="number">10010</span>],ans; <span class="comment">//a为读入数组,ans是记录答案的变量</span></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> n;</span><br><span class="line">cin>>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++) cin>>a[i]; <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++){ <span class="comment">//第一层循环判断哪一个数据还没有到达指定位置</span></span><br><span class="line"><span class="keyword">if</span>(a[i]==i) <span class="keyword">continue</span>; <span class="comment">//发现已就位的数据就跳过</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 class="comment">//第二层循环判断这个位置的正确数据在哪个位置上</span></span><br><span class="line"><span class="keyword">if</span>(i==a[j]){ <span class="comment">//发现正确数据</span></span><br><span class="line">ans++; <span class="comment">//答案增加</span></span><br><span class="line"><span class="built_in">swap</span>(a[i],a[j]); <span class="comment">//交换</span></span><br><span class="line"><span class="keyword">break</span>; <span class="comment">//数据确认后就跳出循环,无需继续判断</span></span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">cout<<ans; <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></pre></td></tr></table></figure>]]></content>
<categories>
<category> 洛谷题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
</tags>
</entry>
<entry>
<title>P4683 题解</title>
<link href="/2024/10/23/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P4683%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/23/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P4683%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>其实就是给你一个<del>很恶心的</del>打印机,共有三种操作:</p><ol type="1"><li>在当前词的尾部添加一个字母;</li><li>在当前次的尾部减去一个字母(至少有一个字母时);</li><li>打印当前词。</li></ol><p>其次,有三个注意点:</p><ol type="1"><li>添加一个字母,用这个小写字母的自身来表示;</li><li>删去一个字母,用减号表示;</li><li>打印单词时,用 <code>P</code> 表示。</li></ol><p>特别的:</p><ol type="1"><li>所有单词都不相同;</li><li>打印结束时,允许有部分字母留在打印机内;</li><li>允许按照任意的次序打印单词。</li></ol><h2 id="思路">思路</h2><p>我们根据贪心策略,我们肯定希望我们最后一个单词尽可能的长,因为这个最长的单词就可以让我们少许多删除操作。</p><p>所以我们可以构建一个字典树,将这个字典树构建出来后,我们把最长的单词找出来,然后对这些单词字母进行标记,在DFS 中我们最后跑这个单词序列,减少回溯。</p><h2 id="代码">代码</h2><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></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><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> N = <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, trie[N][<span class="number">26</span>], cnt, flag[N], k[N], num;</span><br><span class="line">string ans;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">insert</span><span class="params">(string s)</span> </span>{</span><br><span class="line"> <span class="type">int</span> p = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < s.<span class="built_in">size</span>(); i++) {</span><br><span class="line"> <span class="type">int</span> c = s[i] - <span class="string">'a'</span>;</span><br><span class="line"> <span class="keyword">if</span> (!trie[p][c]) trie[p][c] = ++cnt;</span><br><span class="line"> p = trie[p][c];</span><br><span class="line"> }</span><br><span class="line"> flag[p] = <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">void</span> <span class="title">mark</span><span class="params">(string s)</span> </span>{</span><br><span class="line"> <span class="type">int</span> tot = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">auto</span> x : s) {</span><br><span class="line"> <span class="type">int</span> ch = x - <span class="string">'a'</span>;</span><br><span class="line"> k[trie[tot][ch]] = <span class="number">1</span>;</span><br><span class="line"> tot = trie[tot][ch];</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">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> u)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (flag[u] && u != <span class="number">0</span>) {</span><br><span class="line"> num++;</span><br><span class="line"> ans += <span class="string">'P'</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (num == n) {</span><br><span class="line"> cout << ans.<span class="built_in">size</span>() << <span class="string">'\n'</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">auto</span> x : ans) cout << x << <span class="string">'\n'</span>;</span><br><span class="line"> <span class="built_in">exit</span>(<span class="number">0</span>);</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 < <span class="number">26</span>; i++) {</span><br><span class="line"> <span class="type">int</span> res = trie[u][i];</span><br><span class="line"> <span class="keyword">if</span> (k[res] == <span class="number">0</span> && res != <span class="number">0</span>) {</span><br><span class="line"> <span class="type">char</span> tmp = i + <span class="string">'a'</span>;</span><br><span class="line"> ans += tmp;</span><br><span class="line"> <span class="built_in">dfs</span>(res);</span><br><span class="line"> ans += <span class="string">'-'</span>;</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 < <span class="number">26</span>; i++) {</span><br><span class="line"> <span class="type">int</span> res = trie[u][i];</span><br><span class="line"> <span class="keyword">if</span> (k[res] && res) {</span><br><span class="line"> <span class="type">char</span> tmp = i + <span class="string">'a'</span>;</span><br><span class="line"> ans += tmp;</span><br><span class="line"> <span class="built_in">dfs</span>(res);</span><br><span class="line"> ans += <span class="string">'-'</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">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> string t;</span><br><span class="line"> <span class="type">int</span> len = <span class="number">0</span>;</span><br><span class="line"> cin >> 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"> string s;</span><br><span class="line"> cin >> s;</span><br><span class="line"> <span class="keyword">if</span> (s.<span class="built_in">size</span>() > len) {</span><br><span class="line"> t = s;</span><br><span class="line"> len = s.<span class="built_in">size</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">insert</span>(s);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">mark</span>(t);</span><br><span class="line"> <span class="built_in">dfs</span>(<span class="number">0</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>]]></content>
<categories>
<category> 洛谷题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 字典树 </tag>
</tags>
</entry>
<entry>
<title>P4310 题解</title>
<link href="/2024/10/23/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P4310%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/23/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P4310%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<p>题目算法: #动态规划dp ## 题意</p><p>给定一个长度为 <span class="math inline">\(n\)</span> 的序列 <spanclass="math inline">\(a\)</span>,求序列 <spanclass="math inline">\(a\)</span> 的子序列 <spanclass="math inline">\(b\)</span>,使得 <span class="math inline">\(b_i\& b_{i - 1} \not= 0\)</span>,求子序列 <spanclass="math inline">\(b\)</span> 的最大长度。 ## 思路</p><p>碰到与、或、异或这几种运算符时,大部分题目就需要拆解二进制,这道题同理。</p><p>由于题目要求 <span class="math inline">\(b_i \& b_{i - 1} \not=0\)</span>,也就是说这个序列有一个二进制位上这个数列全部是 <spanclass="math inline">\(1\)</span> ,所以我们就可以定义状态 <spanclass="math inline">\(dp_i\)</span> 表示在二进制的第 <spanclass="math inline">\(i\)</span> 为上是 <spanclass="math inline">\(1\)</span>的数字个数,我们每次读入一个数就可以进行暴力转移。</p><p>时间复杂度:<span class="math inline">\(\mathcal O (30n)\)</span>。## 代码</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></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><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">int</span> n, dp[<span class="number">40</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"> cin >> n;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>, x; i <= n; i++) {</span><br><span class="line"> cin >> x;</span><br><span class="line"> <span class="type">int</span> k = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i <= <span class="number">30</span>; i++) </span><br><span class="line"> <span class="keyword">if</span> (x & (<span class="number">1</span> << i)) </span><br><span class="line"> k = <span class="built_in">max</span>(k, dp[i] + <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i <= <span class="number">30</span>; i++) </span><br><span class="line"> <span class="keyword">if</span> (x & (<span class="number">1</span> << i)) </span><br><span class="line"> dp[i] = k;</span><br><span class="line"> ans = <span class="built_in">max</span>(ans, k);</span><br><span class="line"> }</span><br><span class="line"> cout << 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>
<categories>
<category> 洛谷题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 动态规划dp </tag>
</tags>
</entry>
<entry>
<title>P4141 题解</title>
<link href="/2024/10/23/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P4141%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/23/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P4141%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>你有 <span class="math inline">\(n\)</span>个物品,每个物品的体积分别是 <span class="math inline">\(w_1, w_2 \dotsw_n\)</span>。</p><p>定义 <span class="math inline">\(cnt_{i, x}\)</span> 表示不选择第<span class="math inline">\(i\)</span> 个物品(也就是将第 <spanclass="math inline">\(i\)</span> 个物品扔掉),装满容量为 <spanclass="math inline">\(x\)</span> 的背包的方案。</p><p>你需要求出所有的 <span class="math inline">\(i \in [1, n], x \in [1,m]\)</span> 的 <span class="math inline">\(cnt_{i, x}\)</span>的表格(你只需要输出个位数)。</p><h2 id="思路">思路</h2><p>最暴力的方法就是枚举每一个物品,然后对于删掉的这个物品跑一次 01背包。</p><p>但我们没有必要全部枚举,在 01 背包里,我们的转移是<code>dp[j] = (dp[j] + dp[j - w[i]) % 10</code>,而我们删除这个物品不就是将这个转移不转移了,也就是将这个式子给减去,然后就做完了。</p><h2 id="代码">代码</h2><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></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><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> N = <span class="number">2010</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m, a[N], dp[N], g[N];</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"> cin >> n >> m;</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"> cin >> a[i];</span><br><span class="line"> }</span><br><span class="line"> dp[<span class="number">0</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">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> j = m; j >= a[i]; j--) {</span><br><span class="line"> dp[j] += dp[j - a[i]];</span><br><span class="line"> dp[j] %= <span class="number">10</span>;</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">1</span>; i <= n; i++) {</span><br><span class="line"> g[<span class="number">0</span>] = <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 <= m; j++) {</span><br><span class="line"> <span class="keyword">if</span> (a[i] > j) {</span><br><span class="line"> g[j] = dp[j];</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> g[j] = (dp[j] - g[j - a[i]] + <span class="number">10</span>) % <span class="number">10</span>;</span><br><span class="line"> }</span><br><span class="line"> cout << g[j];</span><br><span class="line"> }</span><br><span class="line"> cout << <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>
<categories>
<category> 洛谷题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 动态规划 </tag>
<tag> 背包 </tag>
</tags>
</entry>
<entry>
<title>P4053 题解</title>
<link href="/2024/10/23/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P4053%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/23/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P4053%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>你有 <span class="math inline">\(n\)</span>个建筑,每个建筑需要维修,每个建筑要 <spanclass="math inline">\(x\)</span> 秒才能维修,如果一个建筑在 <spanclass="math inline">\(y\)</span>秒之内没有维修完成,这个建筑就报废了,你需要求出你最多能维修几个建筑。</p><h2 id="思路">思路</h2><p>这 <span class="math inline">\(n\)</span>个建筑如果这个建筑报废的时间越晚,我们肯定越晚维修它。所以我们按照报废时间从小到大排序。然后我们模拟修建筑的过程,如果修道这个建筑时,这个建筑还没有报废,那么答案加<spanclass="math inline">\(1\)</span>,如果报废了,我们要维修的建筑多,所以我们最好只放弃一个维修时间最大的建筑,而维护这个动态的最大值我们就可以使用<code>priority_queue</code> 来维护。</p><h2 id="代码">代码</h2><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"><bits/stdc++.h></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="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> N = <span class="number">1.5e5</span> + <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, ans, sum;</span><br><span class="line">vector<pair<<span class="type">int</span>, <span class="type">int</span>>> v;</span><br><span class="line">priority_queue<<span class="type">int</span>> q;</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"> cin >> n;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>, x, y; i <= n; i++) {</span><br><span class="line"> cin >> x >> y;</span><br><span class="line"> v.<span class="built_in">push_back</span>({y, x});</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">sort</span>(v.<span class="built_in">begin</span>(), v.<span class="built_in">end</span>());</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">auto</span> [y, x] : v) {</span><br><span class="line"> q.<span class="built_in">push</span>(x);</span><br><span class="line"> sum += x;</span><br><span class="line"> <span class="keyword">if</span> (sum <= y) {</span><br><span class="line"> ans++;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> sum -= q.<span class="built_in">top</span>();</span><br><span class="line"> q.<span class="built_in">pop</span>();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> cout << 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>
<categories>
<category> 洛谷题解 </category>
</categories>
<tags>
<tag> 贪心 </tag>
<tag> 题解 </tag>
</tags>
</entry>
<entry>
<title>P3802 题解</title>
<link href="/2024/10/23/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P3802%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/23/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P3802%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>有 <span class="math inline">\(a_i\)</span> 个 <spanclass="math inline">\(i\)</span>(<span class="math inline">\(1 \le i\le7\)</span>),每次从所有未选的中随机选出一个,接在最后面,求连续 <spanclass="math inline">\(7\)</span> 个互不相同的数的组数的期望值。</p><h2 id="思路">思路</h2><p>我们考虑对于去前 <span class="math inline">\(7\)</span>个能量晶体。</p><p>设 <span class="math inline">\(N = \sum_{i = 1}^{7} a_i\)</span>。</p><p>考虑一连串的取出 <span class="math inline">\(a_1, a_2, a_3 \dotsa_7\)</span> 的概率为 <span class="math inline">\(\frac{a_1}{N} \times\frac{a_2}{N - 1} \times \frac{a_3}{N - 2} \times \frac{a_4}{N - 3}\times \frac{a_5}{N - 4} \times \frac{a_6}{N - 5} \times \frac{a_7}{N -6}\)</span>。</p><p>因为是条件概率,所以样本空间减少了 <spanclass="math inline">\((n-x)\)</span>。</p><blockquote><p>[!question] 什么是条件概率? 简单点来解释就是事件 <spanclass="math inline">\(B\)</span> 在事件 <spanclass="math inline">\(A\)</span> 发生的条件下发生的概率。</p></blockquote><blockquote><p>[!success] 举个栗子: 掷色子第一次投 <spanclass="math inline">\(6\)</span> 概率为<spanclass="math inline">\(\frac{1}{6}\)</span>,为 <spanclass="math inline">\(A\)</span> 事件,第二次投 <spanclass="math inline">\(6\)</span> 概率仍为<spanclass="math inline">\(\frac{1}{6}\)</span>,为 <spanclass="math inline">\(B\)</span>事件。如果把两次投掷产生的一个结果算成一个最终状态,那么连续的状态 <spanclass="math inline">\(AB\)</span> 发生的概率为 <spanclass="math inline">\(\frac{1}{36}\)</span>,也即是 <spanclass="math inline">\(B\)</span> 在 <spanclass="math inline">\(A\)</span> 发生的条件下发生的概率。</p></blockquote><p>然后我们发现这个式子不按照 <span class="math inline">\(1 \sim7\)</span>的顺序分子分母依然没有变化,所以我们可以直接排列组合,把所有的顺序全部统计,即:<spanclass="math inline">\(7! \times \frac{a_1}{N} \times \frac{a_2}{N - 1}\times \frac{a_3}{N - 2} \times \frac{a_4}{N - 3} \times \frac{a_5}{N -4} \times \frac{a_6}{N - 5} \times \frac{a_7}{N - 6}\)</span>。</p><p>但其实后面每七位对应的答案都是这样。</p><blockquote><p>为什么?</p><p>举个例子。班主任拿了一个盒盒让你们摸球球,里面有 <spanclass="math inline">\(1\)</span> 个红球和 <spanclass="math inline">\(29\)</span> 个白球(你班 <spanclass="math inline">\(30\)</span>人),抽到红球的人就有了这个至高无上的权利,一个个的去抽,那么顺序不一样的话,是公平的吗?</p><p>是的,我们可以理解成一个机器将 <spanclass="math inline">\(30\)</span> 个球分给 <spanclass="math inline">\(30\)</span> 个人,很明显,每个人分到红球的概率都是<span class="math inline">\(\frac{1}{30}\)</span>。</p></blockquote><p>所以我们最终答案为:<span class="math inline">\(7! \times\frac{a_1}{N} \times \frac{a_2}{N - 1} \times \frac{a_3}{N - 2} \times\frac{a_4}{N - 3} \times \frac{a_5}{N - 4} \times \frac{a_6}{N - 5}\times a_7\)</span>。</p><h2 id="代码">代码</h2><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></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><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">double</span> n, ans = <span class="number">1</span>, a[<span class="number">10</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">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i <= <span class="number">7</span>; i++) {</span><br><span class="line"> cin >> a[i];</span><br><span class="line"> n += a[i];</span><br><span class="line"> }</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">6</span>; i++) {</span><br><span class="line"> ans *= a[i] / (n - i + <span class="number">1</span>) * (i * <span class="number">1.0</span>);</span><br><span class="line"> }</span><br><span class="line"> ans *= a[<span class="number">7</span>] * <span class="number">7.0</span>;</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%.3lf"</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>
<categories>
<category> 洛谷题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 概率与期望 </tag>
<tag> 动态规划 </tag>
</tags>
</entry>
<entry>
<title>P3065 题解</title>
<link href="/2024/10/23/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P3065%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/23/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P3065%20%E9%A2%98%E8%A7%A3/</url>
<content type="html"><![CDATA[<h2 id="题意">题意</h2><p>给定 <span class="math inline">\(n\)</span> 个总长不超过 <spanclass="math inline">\(m\)</span> 的互不相同的字符串,现在你可以任意指定字符之间的大小关系。问有多少个串可能成为字典序最小的串,并输出这些串。</p><h2 id="思路">思路</h2><p>看到与字典序有关的问题,很容易想到建一棵 <strong>Trie(字典树)</strong> 。</p><p>由于题目中可以指定大小关系,所以我们可以先设一个字符串是整个序列中最小的。</p><p>也就是说,这个字符串的第 <spanclass="math inline">\(i\)</span> 个字母在 <strong>Trie</strong> 的第 <spanclass="math inline">\(i\)</span> 层(根节点算第 <spanclass="math inline">\(0\)</span> 层)的所有字母中字典序最小。</p><p>然后,我们就可以将其构成一张图,也就是我们将我们设定的这个最小字母和这个字母同一层的字母连边,因为我们需要知道这里面有没有冲突,也就是要确保这个字符是最小的,也就是没有环。</p><p>而判断环我们就可以用拓扑排序来做。</p><h2 id="代码">代码</h2><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></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><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> N = <span class="number">3e5</span> + <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n;</span><br><span class="line"><span class="type">bool</span> ok[N];</span><br><span class="line">string s[N];</span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Trie</span> {</span><br><span class="line"> <span class="type">int</span> trie[N][<span class="number">26</span>], flag[N], cnt = <span class="number">0</span>, e[<span class="number">30</span>][<span class="number">30</span>], in[<span class="number">30</span>];</span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">insert</span><span class="params">(string s)</span> </span>{</span><br><span class="line"> <span class="type">int</span> tot = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">auto</span> x : s) {</span><br><span class="line"> <span class="type">int</span> ch = x - <span class="string">'a'</span>;</span><br><span class="line"> <span class="keyword">if</span> (!trie[tot][ch]) trie[tot][ch] = ++cnt;</span><br><span class="line"> tot = trie[tot][ch];</span><br><span class="line"> }</span><br><span class="line"> flag[tot] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">find</span><span class="params">(string s)</span> </span>{</span><br><span class="line"> <span class="built_in">memset</span>(e, <span class="number">0</span>, <span class="keyword">sizeof</span> e);</span><br><span class="line"> <span class="built_in">memset</span>(in, <span class="number">0</span>, <span class="keyword">sizeof</span> in);</span><br><span class="line"> <span class="type">int</span> tot = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">auto</span> x : s) {</span><br><span class="line"> <span class="keyword">if</span> (flag[tot]) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> <span class="type">int</span> ch = x - <span class="string">'a'</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < <span class="number">26</span>; i++) {</span><br><span class="line"> <span class="keyword">if</span> (i != ch && trie[tot][i] && !e[ch][i]) {</span><br><span class="line"> e[ch][i] = <span class="number">1</span>;</span><br><span class="line"> in[i]++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> tot = trie[tot][ch];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">topsort</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">topsort</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="type">int</span> cnt = <span class="number">0</span>;</span><br><span class="line"> queue<<span class="type">int</span>> q;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < <span class="number">26</span>; i++) {</span><br><span class="line"> <span class="keyword">if</span> (!in[i]) q.<span class="built_in">push</span>(i);</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="type">int</span> u = q.<span class="built_in">front</span>();</span><br><span class="line"> q.<span class="built_in">pop</span>();</span><br><span class="line"> cnt++;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < <span class="number">26</span>; i++) {</span><br><span class="line"> <span class="keyword">if</span> (e[u][i]) {</span><br><span class="line"> <span class="keyword">if</span> (!--in[i]) q.<span class="built_in">push</span>(i);</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> cnt == <span class="number">26</span>;</span><br><span class="line"> }</span><br><span class="line">} trie;</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"> cin >> 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"> cin >> s[i];</span><br><span class="line"> trie.<span class="built_in">insert</span>(s[i]);</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="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> (trie.<span class="built_in">find</span>(s[i])) {</span><br><span class="line"> ans++;</span><br><span class="line"> ok[i] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> cout << ans << <span class="string">'\n'</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> (ok[i]) {</span><br><span class="line"> cout << s[i] << <span class="string">'\n'</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>]]></content>
<categories>
<category> 洛谷题解 </category>
</categories>
<tags>
<tag> 题解 </tag>
<tag> 字典树 </tag>
<tag> 拓扑排序 </tag>
</tags>
</entry>
<entry>
<title>P2887 题解</title>
<link href="/2024/10/23/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P2887%20%E9%A2%98%E8%A7%A3/"/>
<url>/2024/10/23/%E6%B4%9B%E8%B0%B7%E9%A2%98%E8%A7%A3/P2887%20%E9%A2%98%E8%A7%A3/</url>