11月1日模拟赛题解

T1 猴猴吃苹果

对深度进行二次排序,并深搜就可以了。

T2 猴猴吃香蕉

题意:有\(n\)个香蕉,每个香蕉有一个甜度值,求有多少种方法使得甜度值的乘积恰好等于\(K\)

\(1<=n<=1000,1<=k<=1e8\)

解法:

\(0/1\)背包

但发现空间存不下,所以我们选择用\(map\)进行\(dp\),注意到\(dp\)时背包空间的枚举,枚举的空间必须是\(K\)的因数,而\(K\)的因数个数大概在\(\sqrt K\)\(\sqrt [3] K\)之间(对于\(10^{18}\)范围内的数,约数个数最多约为\(10^5\))。时间复杂度理论最差为\(10^8\)左右,但实际上只有\(10^7\)左右

T3 猴猴的比赛

题意:猴猴和猩猩比赛爬树,两棵树的节点数都为\(n\),每棵树的根节点都为节点\(1\),对于一对满足要求的节点\((u,v)\),在两棵树中,\(v\)的深度都在\(u\)的子树中。求出共有多少对节点满足要求。

\(1<=n<=100000\)

解法:

\(dfs\)序 + 线段树区间修改,单点查询

对于\(1e5\)的数据范围,\(n^2\)的做法显然是无法通过的,所以我们考虑\(nlogn\)的做法。

我们考虑如何判断一个点\(v\)在另一棵树中也在\(u\)的子节点中,我们先深搜一遍另一棵树,求出\(dfs\)序数组\(dfn\)和子树大小数组\(size\)可以发现当满足\(dfn[u]\le dfn[v]\le dfn[u] + size[u]-1\)时,节点\(v\)在节点\(u\)的子树中。

我们考虑如何利用\(dfs\)序的连续性,用线段树解决这个问题。我们一开始的想法是先把每个点子树中的点的\(dfs\)序在线段树中的下标所对应的值区间修改\(1\),然后在回溯时把它区间修改\(0\),但我们考虑到树上进行回溯时只能把父节点的值给回溯掉,所以我们选择在往下深搜时把每个点所对应的子树的\(dfs\)序下标在线段树中全部区间修改\(1\),然后访问到一个点时,单点查询每个点的\(dfs\)序在线段树中所对应的值即可,回溯时区间修改\(1\)即可。

posted @ 2019-11-06 16:01  Akaina  阅读(139)  评论(0编辑  收藏  举报