NOI2015
程序自动分析(并查集)
NOI出这种题我还有什么好说的呢……
拆点并查集即可。
软件包管理器(树链剖分、线段树)
一个支持区间赋值和区间和的线段树+树链剖分即可
寿司晚宴(数论、状压DP)
数论题\(n \leq 500\)肯定是什么暴力算法……
注意到每一个数\(> \sqrt{n}\)的因子最多只有一个,这意味着\(> \sqrt{n}\)的因子之间是独立的,而只有\(\leq \sqrt{n}\)的因子之间会相互影响。而\(\leq \sqrt{n}\)的因子只有\(2,3,5,7,11,13,17,19\)总共\(8\)个,所以可以大力状压。
将\(2-n\)之间的所有数质因数分解,记录其中\(<\sqrt{n}\)的因子的出现情况,按照\(> \sqrt{n}\)的因子分类,一组一组地加入并DP。设\(dp_{i,j,k}\)表示第一个人拥有的寿司中\(<\sqrt{n}\)的因子存在情况为\(i\),第二个人拥有的寿司中\(<\sqrt{n}\)的因子存在情况为\(j\),当前计算的\(> \sqrt{n}\)的因子的存在情况为\(k\)时的方案数,转移看当前寿司分给第一个人还是第二个人。没有\(> \sqrt{n}\)因子的数先单独做一次。
荷马史诗(Haffman树、贪心)
K进制Haffman树直接贪心。注意需要加入若干个\(0\)使得总元素个数是\(K\)的倍数,否则答案可能不优。
品酒大会(SA、并查集)
跟后缀\(LCP\)长度有关,上\(SA\)。求出\(height\),考虑如何对于每一个\(r\)的询问快速求出答案。不妨将\(r\)从大到小求解,那么对于某一个后缀\(sa_k\),满足\(LCP(suffix_{sa_p} , suffix_{sa_k}) \geq r\)的\(p\)一定是一段区间,而且这一段区间随着\(r\)的缩小不断增大。
然后考虑如何拓展区间。考虑对于\(height_k=q\),当\(r>q\)的时候\(k\)位置两端的区间不会越过\(k-1\)与\(k\),而当\(r \leq q\)时这两段区间就会合成一段区间。这个显然是可以使用并查集维护的,并且可以比较轻松地在并查集上维护最大价值。
小园丁与老司机(DP、上下界网络流)
第一问不难得到一个DP:设\(f_i\)表示从起点到\(i\)最多能够经过多少棵树。按照\(y\)坐标从小到大DP,对于每一个\(y\)坐标,先考虑它们下面的点的转移,然后再考虑横向的转移。
再考虑第二问。首先我们需要求出可能留下非左右方向车辙印地面。这个可以这样求:设\(g_i\)表示从\(i\)到任意一个终点最多经过多少棵树,转移跟上面的类似,但是这两种转移有一些细微的差别。在DP的过程中,每当找到一条非左右方向的路径\((x,y)\)时,考虑\(f_x + g_y\)是否等于第一问的最优解,如果等于则表示这一条路需要轧路机。
找到了这些边,然后我们需要求每一条边至少经过一次的最小次数。不难发现这就是一个有源汇有上下界最小流问题,直接做就可以了。
细节比较多,代码比较长,要细心一些~