序
为什么,为什么,为什么小图灵说上海 135pts 就能一等?(听说似乎没了)是否为真需等待时间来揭晓。(135pts 的小蒟蒻)
感觉 T2 好欢乐,每个层次都不复杂但又能区分能力。
T3 赛时代码本质逻辑无误,主要还是对齐方式以及特殊情况的处理有误。
Update:100+35+0+0=135 是二等奖
状态:完结(11/5)
题解
所有代码:code
1. 密码锁
涉及算法:枚举
难度:普及-
解法
由于考虑到所有的密码只有 1 0 5 10^5 105 种,所以枚举所有密码,然后判断一个密码是否可以变形成若干状态即可。
复杂度 O ( 1 0 5 ) \mathcal{O}(10^5) O(105)
2. 消消乐
涉及算法:栈,哈希
难度:提高
解法
35pts
考虑区间 dp,判断每一个区间是否可以被消除。 f ( l , r ) = [ a l = a r ] ⋅ f ( l + 1 , r − 1 ) o r [ f ( l , k ) a n d f ( k + 1 , r ) ] f(l,r)=[a_l=a_r]\cdot f(l+1,r-1)\;or\;[f(l,k)\;and\;f(k+1,r)] f(l,r)=[al=ar]⋅f(l+1,r−1)or[f(l,k)andf(k+1,r)]。
复杂度 O ( n 3 ) \mathcal{O}(n^3) O(n3)
50pts
考虑栈,可以参考这题(cf原题)的题面。固定区间左端点,然后向右不断将元素入栈,若当前元素和栈顶元素相同则弹栈顶元素。栈大小为 0 时答案统计一次。
复杂度 O ( n 2 ) \mathcal{O}(n^2) O(n2)
100pts
考虑上一个做法存在的问题:多次扫描入栈有重复信息。这里提供一种通过哈希的解决方案。从第一个开始向右不断将元素入栈,若当前元素和栈顶元素相同则弹栈顶元素。假如两个不同时刻栈内元素相同,那么中间过程是可被消除的,因此我们只要知道有多少时刻栈内元素与现在相同就行,这个可以通过 hash 和 map 实现。
复杂度 O ( n log n ) \mathcal{O}(n\log n) O(nlogn)
3. 结构体
涉及算法:模拟,二分,STL运用
难度:提高
解法
显然,对于一个类型或一个元素,要储存的内容过多,所以用结构体表示一个类型或一个元素。值得注意的是,类型嵌套存储肯定炸空间,所以我们只存名字,然后用 map<string,Type> TypeLib
对其映射。每个操作都可以照着逻辑实现,除了最后一个可以用二分查找,其它并无思维上难点,主要考验代码力。复杂度很小,故不做考虑,详情实现看代码(变量名字已经很能说明问题了)。
4. 种树
涉及算法:二分,贪心
难度:提高+
解法
这样的题目第一反应是二分答案,顺此往下想如何写 check
。显然可以
O
(
n
)
\mathcal{O}(n)
O(n) 求出每一棵树最晚何时种,记为
t
i
t_i
ti。进而发现本质上是决定一个排列,表示第
i
i
i 棵树第
p
i
p_i
pi 天种,满足树的遍历顺序,且
p
i
≤
t
i
p_i\leq t_i
pi≤ti。继续我们想到成立时,对于每一条边
u
→
v
u\to v
u→v,必然满足
p
u
≤
p
v
−
1
≤
t
v
−
1
p_u\leq p_v-1\leq t_v-1
pu≤pv−1≤tv−1。假如存在排列使树中此条件总成立,对其验证即可说明充分性(继续推理可发现,最终构造的不同排列总是等价的)。所以我们可以通过树上 dfs(或者可以算是 dp),求出
p
u
=
min
v
∈
s
u
b
u
t
v
+
d
i
s
u
v
p_u=\min_{v\in sub_u}t_v+dis_{uv}
pu=minv∈subutv+disuv,然后离散再验证一下。
其实解释方法有很多,但是都不算很好想,建议读者自己动动脑。
最后看复杂度,显然为 O ( n log 2 n ) \mathcal{O}(n\log^2n) O(nlog2n),细节需要卡一下常才可保证通过。