NOIP2024集训 Day47 总结

前言

人有两次生命,当他意识到只有一次的时候,第二次生命就开始

最小生成树和二分图匹配专题,感觉总体都比较套路。

但是这些套路为啥感觉见都没见过啊,怪不得做这么慢。

观察到对于最终答案显然都是最小生成树上一条两个端点颜色不同的边。

而这个题并不会改变图的形态,仅仅是改变颜色。

故你考虑维护每一个父亲节点,每一种颜色的儿子都开一个 multiset(你可以开一个 map 来方便实现这个过程),在维护一个答案的 multiset,维护的时候注意一下插入和删除的细节即可。

复杂度 nlog2n,但是常数巨大。

Code

最小公倍树

一个有趣的事实是,你考虑枚举 gcd,1r,然后在枚举它在 [l,r] 之间的整数倍是哪些数,这一部分显然是个调和级数,O(nlnn)

然后你看他们之间怎么连边,假设这些合法的 gcd 的整数倍分别是 a1,a2,...am

显然,你考虑将 j[2,m] 连一条 (aj,a1,aj×aigcd) 的边即可。因为你本质上只需要将同一层的 gcd 连向最小的一个点即可,毕竟他和其他点连的边权显然是最小的。(这个 trick 其实出现在了后面的题目里面,就是本质上你边权相同的点你可以只连一个菊花,而没有必要两两互相建边,是非常重要的。)

另外,如果他不是最大的 gcd,那么使用它显然不会更优,故这样连边不会出错。

连边之后直接跑 Kruskal 即可。

复杂度应该是 O((rl+1)×(lnr)×(log(rl+1)))

Code

Power Tree

这个题题解区有通过差分而得到的非常巧妙的最小生成树做法,这里讲一下自己输出方案巨恶心的动态规划做法。

定义 dpi,0 表示将 i 子树之下的叶子节点全部变为相同所需要的最少代价。

定义 dpi,1 表示将 i 子树之下的叶子节点可以变为任意数的最小代价。

显然有转移:

dpi,0=mindpjsoni,0+ksoni,kjdpk,1

dpi,1=mindpjsoni,0+ksoni,kjdpk,1+wi

然后这个输出方案巨恶心,因为你要把所有可能的都输出。

Code

City 城市建设

非常重要且典的题,可是我根本不会,所以像我这种脑子不好使的人赶紧去学 LCT 吧。

你考虑对于操作询问进行线段树分治。

我们观察到两个性质。

  • 如果你将修改的边赋为 inf,跑完最小生成树之后,此时不在树上的边一定不在最终的最小生成树上。
  • 如果你将修改的边赋为 inf,跑完最小生成树之后,此时在树上的边一定在最终的最小生成树上。

故你每次递归儿子的时候就只留下有用的边,然后把一定会用上的边先用并查集维护上,这样你每次需要跑的点和边都是这个区间的长度从而达到复杂度平衡。

时间复杂度 O(qlogq×α(n))

Code

新年的繁荣

参考一下今天的第二题。

观察到边权并不会很大,你考虑 Kruskal 求最大生成树的过程,从大到小枚举边权,然后合并连通块。

首先对于那些点权相同的点你可以相互之间直接合并,这样显然不劣。

然后你发现假设当前边权是 x,你考虑找到所有含有点 y,x|y 的连通块。

观察到这些连通块显然不超过 m 个,且每个连通块中必然包含 x2i,如果不包含那我显然可以在更高边权的时候将 x2i 合并进这个连通块,显然更优,如果超过了 m 个显然通过鸽巢原理我仍然可以在更高位的地方合并。

所以你跑一遍类似高维后缀和的操作找到这些连通块然后分别合并即可。

时间复杂度 O(m×2m×α(2m))

Code

免费道路

一道比较智慧的题,但是我居然没有想到,我是废物。

你考虑先求出必须要用的鹅卵石路,即你在跑生成树的时候,先跑水泥路,再跑鹅卵石路就可以得到。

然后你再跑一遍生成树,先把必须要用的鹅卵石的路加上,然后先跑鹅卵石路再跑水泥路,鹅卵石路数量到了 k 个那就别再往生成树里面加鹅卵石路即可。

显然这样是对的,因为你用了必须用的鹅卵石路之后,不管你鹅卵石路后面怎么取,水泥路都有办法让他变成一颗生成树。

无解显然只有三种情况:

  • 图不连通。
  • 必须用的鹅卵石路 >k
  • 跑完第二遍生成树之后,你尽可能多的用鹅卵石路仍然没用到 k 条。

Code

Sorting a Grid

一道还不错的建模题,大致是会的。

你先考虑合法的情况下, b,c 需要满足什么条件。

显然,c 是必须让每一行的数都包含了这一行最终应有的元素。

故你考虑将 x 染上 xm 这种颜色,你发现合法的 b,c 满足:

  • c 每行的颜色相同。
  • b 每列的颜色有 n 种。

显然,对于 b 你可以通过求一个二分图完美匹配得到。

观察到每一个 b 显然都会对应它唯一的 c

时间复杂度 O(n2m2)

Code

全场唯一板子。你将 (i+j) 为奇数的时候看成左部节点,为偶数的时候看成右部节点,然后跑一个最大独立集即可。

Code

后记

撒花~

posted @   Saltyfish6  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
Document
点击右上角即可分享
微信分享提示