「考试总结」ZROI-21-NOIP冲刺-TEST10 总结
...too young...too simple,sometimes naive!
#T1 不知道高到哪里去了
Time Limits: 3s | Memroy Limit: 256MiB
#题意简述
比你们不知道高到哪里去了!
一个 \(n(n\leq10^4)\) 个点 \(m(5\times10^5)\) 条边的带权无向图(可能有重边、自环),你处在 \(C\) 点,刺客开始时在 \(I\) 点,你要到 \(T\) 点去,你不知道刺客向哪里走,刺客时刻知道你的位置,问你的速度至少是刺客的多少倍(实数)才能安全到达 \(T\) 点,如果无法到达,则输出 -1
。
#大体思路
考虑二分答案,考虑如何判定。显然我们可以得到每次到达任意一点的最小时间,刺客的最小时间可以提前用最短路得到,当我们发现当前边的终点的最小时间比刺客晚,那么我们就不前往,看最终是否能够到达 \(T\) 点即可。时间复杂度为 \(O((m+n)\log^2 n)\).
#Code
1 |
|
#T2 身经百战
Time Limits: 1s | Memroy Limit: 256MiB
#题意简述
我是身经百战了,见得多了!
身经百战的你要和怪物战斗。有 \(n(n\leq10^6)\) 个怪,每个怪的血量 \(v_i(v_i\leq10^9)\) 都是一个非负整数,当血量变为负数后怪就死了。有 \(m(m\leq10^5)\) 种魔法,第 \(i\) 种用一个三元组 \((a_i,b_i,c_i)\) 表示,魔法可以重复使用。
你有两种操作可以做:
- 花费 \(1\) 点能量,给一个怪的血量减掉 \(1\)。
- 如果一个怪的血量是 \(a_i\),你可以花费 \(c_i\) 的能量把它的血量变为 \(b_i\)。
你希望削弱这些怪,但你不想杀生。请问最少要花费多少能量才能把所有怪的血量都变成 \(1\)。注意:一个血量为 \(0\) 的怪仍然是存活的。
数据保证有解。
#大体思路
不难发现每个怪物都是独立的问题,所以其实可以看作多次询问,同样因为这个原因,我们尝试进行 DP。
\(f_{i,j}\) 表示将第 \(i\) 个怪物的血量变为 \(j\) 所需要的最小代价。注意到这个 DP 的转移具有后效性,所以考虑将所有转移变为边,找最短路,我们发现上面的状态设计有许多的冗余状态,我们只需要保留给出数据中出现的数,将原本 DP 的转移变为边则是 \(a_i\to b_i\) (边权为 \(c_i\))以及 \(x_i\) 向所有比它小的数连边(边权为差值),但是这样的边的数量仍旧是 \(O(m^2)\) 级别的,不能接受,注意到第二部分的边可以被简化,也就是 \(x_i\) 只需要向比自己小的第一个数连边即可,这样得到的转移图与之前是等价的,边的数量为 \(O(n+m)\),现在我们只需要建出反向边,以 \(1\) 为源点最短路即可。
时间复杂度为 \(O((n+m)\log(n+m))\).
#Code
1 |
|
#T3 跑得比谁都快
Time Limits: 3s | Memroy Limit: 256MiB
#题意简述
你们有一个好,全世界跑到什么地方,你们比其他的西方记者啊,跑得还快。
这条路上有 \(n(n\leq2\times10^5)\) 个红绿灯,把路分成了 \(n+1\) 个部分。红绿灯的颜色是循环的,一次循环内,在 \([0,g)\) 的时间里它是绿色的,在 \([g,g+r)\) 的时间里它是红色的。一开始,每个红绿灯都处于循环的开始,也就是说都会先绿 \(g(g+r\leq10^9)\) 的时间。
记者团里有 \(q(q\leq2\times10^5)\) 个香港记者。每个记者要从路的开头跑到末端,遇到红灯的话不能穿过,必须等红灯变绿。记者的最大速度是 \(1\),记者可以瞬间改变自己的速度。告诉你记者出发的时间,问你她什么时候跑到。
本题强制在线,假如输入的第 \(i(1<i\leq q)\) 个记者的出发时间为 \(time_i\),那么她实际出发的时间是 \(time_i\text{ xor }(ans_{i−1} \bmod 2147483647)\),其中 \(ans_{i−1}\) 表示第 \(i−1\) 个人的到达时间。
#大体思路
考虑在任意红绿灯出发遇到的第一个红灯的位置,由于 \(m=g+r\) 是周期,所以不妨将时间通过 \(\bmod m\) 将所有时间分为 \(m\) 种,设 \(t_i\) 为到达 \(i\) 号红绿灯前没有任何一个红绿灯阻挡到达 \(i\) 的时间,显然是 \(s_i\bmod m\)(\(s_i\) 为 \(len\) 的前缀和),设 \(j\) 为从 \(i\) 出发后遇到的第一个红灯,由于两者之间没有任何红灯阻拦,考虑到从任意一个红绿灯出发必然是在该红绿灯进行了停顿,但显然不会对到 \(j\) 的时间和到 \(i\) 的时间之间的差值造成影响,且出发时间必然是 \(m\) 的倍数,在 \(i\) 于是两者之间经过的时间必然是 \(t_j-t_i=km+b\),\(k\in Z,b\in[g,r)\),于是我们找 \([t_i\bmod m+g,t_i\bmod m+r)\) 区间最小值即可,然后采用 \(j\) 到终点的时间更新 \(i\) 到终点的时间,最后将 \(i\) 插入到 \(t_i\bmod m\) 的位置即可。
再来看查询时,同样考虑第一个遇到的红绿灯,不过上面维护出的都是开始时间为 \(0\) 的情况(循环从头开始),所以我们开始时需要将查询区间进行矫正。
时间复杂度为 \(O(n\log n)\).
#Code
1 |
|
#T4 人生经验
Time Limits: 1s | Memroy Limit: 512MiB
#题意简述
我作为一个长者,来告诉你们一些人生的经验…
人生经验以 01 字符串的形式存在。
一个长度为奇数的 01 字符串是好的,当且仅当它可以被用下面的办法转化为 1
:
- 选一个奇数 \(i(3\leq i\leq|S|)\)
- 把 \(S\) 分成两个字符串 \(A,B\) 满足 \(|A|=i,|B|=|S|−i,S=AB\)
- 通过一个给定的函数 \(f(U)\) 将 \(A\) 的末尾三位数变为一位数,一直重复直到 \(A\) 只剩下一个数
- 用 \(A+B\) 替代 \(S\)。
现在给定一个字符串,包含 0
1
?
三种字符,?
可以替换为 0
或者 1
,请问有多少种替换方案使得替换的结果是一个好串。
#大体思路
DP 套 DP。
我们考虑如何判断一个串是否合法,不难发现,那些操作都可以转化成下面两个操作:
- 把两个字符压入栈。
- 把一个字符压入栈,进行缩字符串,然后再让另一个字符入栈。
虽然栈的情况可能很多,但其实去掉我们不管的,只有 \(4\) 种情况:
- 当前栈中序列加入
1
之后能缩成1
。 - 当前栈中序列加入
1
之后能缩成0
。 - 当前栈中序列加入
0
之后能缩成1
。 - 当前栈中序列加入
0
之后能缩成0
。
上面四种情况就是我们所关心的。然后我们就可以设计 DP 状态:
\(f_{i,a}\) 表示考虑前 \(i\) 个字符,第 \(a\) 个放法是否合法,然后考察整个字符串的话,只需要看 \(f_{n−1}\) 即可。
接下来我们考虑计数,通过上面的启发,再加上字符串是不确定的,所以我们设状态 \(g_{a,b,c,d}\) 分别表示上面 \(4\) 种转移是否合法,\(f_{i,S}\) 表示考虑到第 \(i\) 位,合法转移为 \(S\) 的情况的数量。
我们每次考虑两个数,先考虑两个字符压入栈的情况,然后枚举合法情况,转移即可。
#Code
1 |
|