NOIP 模拟赛:2024-11-26
T1:
当你发现你的算法仅对 \(n\ge\) 一个小值时正确,不如把 \(n<\) 它的情况都打表/特判了。
请构造满足如下要求的序列
- 首先,元素在\(1\sim n\)的所有整数中选,每个整数最多出现一次;
- 其次,保证序列中相邻的元素都不互质;
- 最后,在满足前述条件的基础上,使得序列最长。
请输出构造的序列长度和该序列。
容易想到这么一个构造:偶数都放进来;奇数,如果存在两个偶数和它都不互质,插入到这两个之间;然后挑两个只存在一个偶数和它不互质的数放两边。
线性筛求出每个数的最小质因数即可。细节比较繁琐,为了避免在特殊数据下出错直接把 \(n\le 20\) 的判了。
T2:
当你试图增加优化,思考两件事:
-
它真的有必要吗?
-
它会使得正确性出错吗?
有一间无限酒店有无穷多个房间,编号为\(0,1,2,\cdots\)。酒店每个房间能住一个人,并且只接待团体入住。将要入住的团体按顺序从\(1\)开始编号。
由于是无限酒店,一个新的团队来了总能顺利入住,具体方式为
- 如果团队人数有限:记团队人数为\(k\),则先将每个原\(x\)号房间的人都移动到\(x+k\),然后让新的团队入住在\(0\sim k-1\)号房间;
- 如果团队人数无限:先将每个原\(x\)号房间的人移动到\(2x\),然后让新的团队入住在奇数编号房间。
你需要维护酒店的如下操作需求
1 k:如果\(k>0\),表示有\(k\)人的团体入住酒店;如果\(k=0\),表示有无穷多人的团体入住酒店。注意团体按本操作的顺序从\(1\)编号;2 g x:输出编号为\(g\)的团体占据的房间中,第\(x\)小的房间编号,对\(10^9+7\)取模;3 x:输出此时\(x\)号房间中的客人对应的团体编号。
认为开始时所有房间都住着一个来自\(0\)号团体的人。
每个团队的人的房间编号可以视作一个函数 \(ax+b\)。对于操作 1,原本所有团队 \(b\leftarrow b+k\),新加入一个 \(1\cdot x-1\);对于操作 2,查询 \(a_g\cdot k+b_g\) 即可;对于操作 3,记录之前所有修改操作,如果是 \(k=0\),此时若 \(x\) 是奇数,就是这次修改操作加入的团队,否则 \(x\leftarrow x/2\);否则,若 \(x<k\),就是这次的团队,否则 \(x\leftarrow x-k\)。
前两种操作可以线段树,甚至可以只打全局 tag 完成。瓶颈在于操作 3。
首先,操作 3 的 \(x/2\) 情况最多 \(30\) 次就 \(x=0\) 了。对每次修改操作记录 \(lst2\) 表示上一个非 \(x/2\) 的修改位置,供 \(x=0\) 时跳过即可。
其次,再对每一段非 \(x/2\) 的修改操作记录前缀和。如果 \(x\) 比这一段的 \(\sum k\) 还大,直接减去,然后跳过这一段。因为每跳过一段就会遇到一个 \(x/2\),复杂度不用担心。
如果 \(x\le \sum k\),二分即可。
T3:
有\(n\)个城市,编号\(1\sim n\),你在旅行中希望前往\(n\)号城市。对于所有\(1\le i < n\),都有一个参数\(T_i\),表示从\(i\)号城市出发可以坐大巴直接到达\(i+1,i+2,\cdots,i+T_i\)号城市,注意通行是单向的。
给定正整数\(K\)和非负整数\(D\),表示如果从\(i\)号坐大巴直接到达\(j\)号,则疲劳度会增加\(\lfloor \frac{j-i}{K} \rfloor \cdot D\)。疲劳让人不高兴。
\(i\)号城市具有\(H_i\)的风景值,可能为负。风景越好,人越高兴。
最终,从一个城市去往\(n\)的总快乐度为所有经过的城市(包括起点和终点)的风景值总和减去所有移动的疲劳度总和。
请对每一个可能的起点城市,求出旅行的最大快乐度是多少。
按 \(j-i\) 模 \(k\) 的余数分类,然后线段树优化 DP 即可。具体分析可以画一个 \(k\times n/k\) 的表格。
T4:
给定两棵树\(T_1,T_2\),一棵是有\(n\)个结点的带边权树,另一棵也是有\(n\)个结点的带边权树。两棵树的的结点编号都为\(1\sim n\)。
定义\(dist(T,i,j)\)表示树\(T(T\in \{T_1,T_2\})\)上结点\(i,j\)的简单路径权值和。
定义两个结点编号\(i,j\)的距离为\((dist(T_1,i,j)+dist(T_2,i,j))\)。请对每一个确定的编号\(i\),找出编号\(j\)使得编号\(i,j\)的距离最小,你只需确定最小的距离。
\(n\le 10^5\)。
树上路径问题先无脑考虑点分治,点分治不太行考虑点分树。发现做不了也留一个心眼,说不定暴力枚举套一个树高 \(\log n\) 的条件就对了。
两条路径涉及四个点的编号:\(i,j,l_1,l_2\),其中 \(l_1,l_2\) 是 \(i,j\) 在两棵树上的 LCA。
考虑枚举 \(i\) 和 \((l_1,l_2)\),根据 \((l_1,l_2)\) 找出最优的 \(j\)。当确定了 \(i,l_1,l_2\),变化的量只有 \(dist(T_1,j,l_1)+dist(T_2,j,l_2)\)。因此,我们希望对每个对 \((l_1,l_2)\) 求一个 \(f(l_1,l_2)\) 表示在 \(l_1,l_2\) 的子树内到它俩的距离和最小的结点。
为了避免 \(f()\) 刚好取到 \(i\) 导致出现 \(i=j\) 的不合法情况,让 \(f()\) 再记录一个次小的结点。
这肯定过不了,但如果我们把 \(T_1,T_2\) 的点分树建出来,\((l_1,l_2)\) 的对的数量总共 \(n\log^2 n\) 个,这就可以了。
还有一个问题:怎么存 \(f(l_1,l_2)\)?不能用 map,会多一个 \(\log\)。
答案是不存。记录一个数组 \(g\)。算法直接枚举 \(l_1\)(\(O(n)\)),在 \(T_1\) 点分树上搜索 \(l_1\) 的子树(\(O(n\log n)\)),对搜索到的每个结点 \(i\) 枚举在 \(T_2\) 点分树上的祖先 \(l_2\)(\(O(n\log^2 n)\)),让 \((i,l_1,l_2)\) 更新 \(g[l_2]\)。
搜完的 \(g\) 数组就是当 \(l_1\) 固定时的 \(f\)。此时再搜一遍 \(l_1\) 的子树,更新 \(ans[i]\) 即可。

浙公网安备 33010602011771号