11月3日考试题解

关于这场考试


前言:

关于题目正解

先报一下题目正解,大家最好还是不要直接看题解,多思考一下总会有好处的。

第一题: $ NOIP~2013 $ 小黄题【花匠】(最后10分加强了一下,同样的贪心)

第二题:树状数组优化 $ DP $

第三题:状态压缩, $ DFS $ ,异或在树上的性质

关于码量和难度:

这套题的码量着实不大,加起来都没有一道大数据结构多,像 $ T3 $ 部分分比正解的码量还要大。题目其实都是常规题, $ T1 $ 就是看你原题落实及思维拓展, $ T2 $ 是需要一些 $ DP $ 去重的硬实力的, $ T3 $ 就是看那些降复杂度的小技巧你还记不记得了。题目应该偏向思维难度吧,反正时间分配很重要,尤其是像 $ NOIP,CSPS $ 这种考试时间为三个半小时,比较短的,容易让人慌的考试。

然后其实出题人出完题目后心里还是有点小忐忑的,听到要考自己的题当晚没睡着,感觉自己失去了题目难易好坏的把控,希望不会被喷吧。出题人自我感觉难度应该和码量成正比,题解也就按这个顺序吧。

第一题:命运(乱搞贪心)( $ NOIP $ 小黄题)

$ Noip~2013 $ 花匠

像这种题目,要观察每一步的决策优劣:(前后两个数的对比)
这道题很容易让人想到线性动规,因为状态只和当前序列末尾元素大小有关。
只要你深入观察每一步策略的最优性,你就会发现这道题其实就是求波峰波谷。
对于每一段单调上升或下降的区间,我肯定取最后一个最优。
然后我们讲一下贪心优劣的判断。。。。。

90分:

先分两种情况

  1. 最后得到的事件序列最开始是先小后大
  2. 最后得到的事件序列最开始是先大后小

然后我们贪心,我们记录一个变量 $ v=a[1] $ ,如果下一个要放大的,那么当我们扫描到 $ i $ 时:

  1. 这个数比 $ v $ 大,我们直接将这个数放到最终序列末尾,然后 $ v=a[i] $ ,我们下一个放小的。
  2. 这个数比 $ v $ 小,我们将 $ v $ 改为 $ a[i] $ 。因为这个数比当前序列末尾更好,它更容易让后面的数变成高峰。

如果下一个要放小的,那么当我们扫描到 $ i $ 时:

  1. 这个数比 $ v $ 小,我们直接将这个数放到最终序列末尾,然后 $ v=a[i] $ ,我们下一个放大的。
  2. 这个数比 $ v $ 大,我们将 $ v $ 改为 $ a[i] $ 。因为这个数比当前序列末尾更好,它更容易让后面的数变成低谷。

将两种情况得到的最终序列的长度取最大值之后就可以得到答案了!

100分:

其实和 $ K=0 $ 时是一样的,直接求波峰波谷(但是波峰波谷的定义有所改变),这个不难,留作思考。

第三题:异或在树上的特殊性质

题目大意:

原题面很清晰,不做概括。而且这道题 $ m $ 的范围真的很容易让人想到状态压缩。我们将边的奇数偶数的变化用二进制和位运算表示后可以得到另一个“题面”:有一棵树,每条边上都有一个权值,现在给你一个二进制数,求树上有多少条路径,使得【路径上每条边的异或和】再异或上【这个数】之后等于 0 。

如果你能仔细思考这个题目并将题面转化成上面这个样子,那么你已经很接近正解了,再多思考一下吧。如果你还没有推出这个题面,现在你知道了,也再思考一下吧。题目不难,重在异或的性质。


20分: $ O(n^2\times m\times t) $

这一档分是为了照顾不会状压的同学。直接暴力枚举路径并计数,然后判断奇偶。


40分:(对应小暴力程序) $ O(n^2\times t) $

考虑状态压缩。因为题目只需要知道出现次数是奇数或偶数(不需要知道具体多大),所以将奇数都用 $ 1 $ 表示,偶数都用 $ 0 $ ,这样如果未知系数的个数每增多一个,就用异或运算来翻转奇偶性。因为只有 $ 20 $ 种不同的未知系数,所以我们用 $ 20 $ 个不同的二进制位来存储,压到一个 $ int $ 里就好了。


60分:对应大暴力 $ O(nlogn \times t) $

这档分本来是给 $ trie $ 树的,如果你数据结构够强,也可以写淀粉质或者树上启发式合并。
不过这档分是不会多讲的,毕竟复杂度没正解优秀,码量还极大。( $ dfs $ 居然吊打了数据结构?真舒服)


80分:一条以根为端点的链

其实出题人是良心的,这档分离正解最近,非常具有启发性。

我们知道一条链可以近似为一个数列,所有路径都是其子区间。而【区间异或和】可以通过【前缀异或和】快速得到。我们可以枚举每一个点作为右端点统计有多少合法左端点。如何计算呢?对于每组询问,我们将这个询问拆成两个状压后的二进制数,第一个 $ y $ 表示对于每个二进制位是否有限制,第二个 $ x $ 表示对于每个二进制位它要求是奇数还是偶数(没有限制的也为 $ 0 $ )。然后对于一个右端点可以将其【前缀异或和】和 $ y $ 取与运算(消掉没有限制位的贡献),然后将这个数和 $ x $ 异或,得到其对应的左端点的【前缀异或和】应该是多少。这个可以用一个值域的桶,记录前缀异或和来快速查询。

这个转换询问的方法在谢总 $ vjudge $ 上布置过的 $ UVA565PizzaAnyone? $ 里曾出现过。


100分:(请先仔细阅读上面一条链的题解) $ O(n\times t) $

还记得 洛谷 $ P4551 $ 最长异或路径吗?学 $ OI $ 还是要记得一些常规套路的。本题的套路出自异或在树上的一个特点:我们任选一个点作为根,从它开始遍历树,得到 $ n $ 条到根路径的状压信息存到数组 $ a[] $ 中。因为异或的特点,树上的任意一条路径都可以用这 $ n $ 个数中的两个相互异或得到(因为同一条边被异或两次相当于没有被异或)。

观察题目细节,我们发现 \(m\leq 20\) ,也就是说所有二进制数都小于 $ 1048576 $ 。于是开个值域的桶子维护每个数出现的次数。然后对于每个询问我们分开做,先遍历一遍 a[] 数组将所有值都和 $ y $ 与运算记录到值域桶子中。然后再遍历一遍 $ a[] $ 数组,将每个数和 $ y $ 取与运算再和 $ x $ 异或,得到它对应的另一条到根路径的状压数是多少,然后直接到桶子里找到对应下标即可知道有多少对应路径了!(具体实现看代码)

关于本题考场修改数据范围的致歉:

因为出题人和验题人的疏忽(太菜了),并不知道有一个吊打标算的 $ n+m\times 2^m+t\times 2^{m/3} $ 的 $ t $ 甚至可以达到 $ 10^6 $ 的神仙 $ \mathrm{fwt} $ 做法。为了引导鼓励大家使用 $ CSP $ 范围的算法,做出了这个具有针对性的决定。

出题人和验题人在此向 \(Itst,Iotang\) 等写完代码又好心告诉出题者这个做法的同学表示诚挚的感谢;同时也向这些写完算法却又被辣鸡出题人卡的同学表示十分沉重的歉意。当然,你们也可以上台分享这个做法,毕竟吊打了标算。

第二题:树状数组优化 $ DP $

题目大意:

有 $ \sum x $ 个二元组 $ (v,id) $ 组成的一个序列,求其中最长的满足 $ v $ 和 $ id $ 都单调递增的最长上升子序列的方案数!仔细思考这道题,你会发现它难在去重。而这道题的原型大家肯定都做过,是谢总布置过的 $ BuylowBuy~lower$ (对应洛谷 $ P1108 $ 低价购买)不知道大家看出来没。

30分: $ O(n3)~or~O(n2\times log) $

由选手自由发挥,不做多讲,可以分享。

60分: $ O(n^2) $

可以去看看 $ vjudge $ 上的原题(你要是敢说没写过,我现在就去找谢总)。

这档分有很多种写法,先讲一下以不同的商店为重心,作为一个启发。首先我们定义一个结构体 $ (l,tt) $ 和结构体数组 $ s[] $ 。 $ s[i] $ 记录目前子序列里最后一个五彩棒权值为 $ i $ 的子序列的信息,其中 $ s[i].l $ 记录所有末尾权值为 $ i $ 的子序列的最长长度(注意是最长,因为若不是最长的子序列,肯定不能将方案贡献到最终答案), $ s[i].tt $ 记录所有末尾权值为 $ i $ 的不同的最长子序列的总数。

然后我们将所有五彩棒(或者说二元组),以商店编号为第一关键字、权值为第二关键字排序。因为我们以商店从小到大遍历,于是只需担心五彩棒权值是否单调递增。所以每次枚举到一个五彩棒 $ (v,id) $ (注意名称,后面会用),我们在 $ s[] $ 数组中找到所有末尾权值比它小最长不同子序列的长度及个数 $ (L,TT) $ (注意名称,我大写了),然后将这个信息计入到 $ s[v] $ 中去。因为可能产生重复,我们不难想到:第一,如果 $ s[v].l=l $ 那么说明之前有一个同样权值的五彩棒,会产生重复,但是前面那个五彩棒能组成的方案这个五彩棒都可以,所以转移为直接覆盖 $ s[v].tt=TT $ ;第二,如果 $ s[v].l<l $ 那么说明之前的五彩棒都不满足最长这个条件,不会产生重复,所以直接覆盖 $ s[v].l=L; s[i].tt=TT $ 。

因为每个商店最多买一个,对于同一个商店我们不能边转移、边更新。所以我们将同属于一个商店的五彩棒先统计出所有末尾权值比它小最长不同**子序列的长度及个数,计入 $ k[] $ 数组,然后再遍历一遍进行上述转移更新。

100分: $ O(logn\times \sum x) $

在上面那个算法里, $ s[i] $ 数组只需要统计前缀最大,更新也只要更新前缀最大。所以这个数组我们可以用树状数组来维护,做到 $ log $ 的询问和修改!置于怎么维护 $ s[i] $ 数组,可以参见上面去重的那一段(那个第一、第二、那里)。然后上面说的这种方法,树状数组维护的是五彩棒值域,需要离散化。标程以五彩棒权值为排序第一关键字,树状数组里维护的是子序列末尾那个五彩棒的商店编号,所以不需要离散化,大家可以思考一下以不同的商店为重心,怎么维护,大体是一样的,只是去重有些差别。

然后,洛谷上也有一篇 $ nlogn $ 的低价购买的题解,不过很尴尬的是他的做法复杂度是假的。但是也正要感谢他,让我知道了还有一种假做法,于是我就……..把它卡掉了。

然后如果你写了正解被卡常,可以来申诉;但是如果你写了线段树,那可能比较难过,视常数 $ 80-100 $ 不等吧。

posted @ 2019-11-03 20:12  一只不咕鸟  阅读(350)  评论(4编辑  收藏  举报