训练记录PART6 2018.8.16~11.28
友情提醒:大部分题选自opentrains,以后有训练需要的同学慎重查看。
2018 ICPC Asia Jiaozuo Online C
题意:内存32M。有 \(N(\leq 10^5)\) 个数字(元素 \(\leq N\))和 \(M(\leq 10^5)\) 个询问 \((l_1,r_1,l_2,r_2)\),每次求 \(\sum \limits_{i=l_1}^{r_1} \sum \limits_{j=\max(i,l_2)}^{r_2} (j-i+1) \times \max(a_i,\dots,a_j)\)。
题解:此题的关键是,不要被 \(i\) 和 \(j\) 的大小关系的要求困惑住。
先假设不用乘 \((j-i+1)\)。有 \(max\) 在式子里,容易想到建立笛卡尔树,按最大值分治。每次固定了一个最大值的位置 \(k\) 后,我们可以求出它能造成贡献的所有 \((i,j)\) 的范围(\(p \leq i \leq k,k \leq j \leq q\),其中 \(p-1\) 和 \(q+1\) 是两侧第一个比 \(a_k\) 大的数的位置)。将两维看做矩阵,执行 \([p,k] \times [k,q]\) 矩阵加操作。而对于询问的 \((l_1,r_1,l_2,r_2)\),只要无脑在 \([l_1,r_1] \times [l_2,r_2]\) 上矩阵求和即可。注意不必特殊在意 \(i \leq j\) 的限制,因为在矩阵加的时候,已经保证了坐标合法。
注意到此处是有先后顺序的:先全部矩阵加完,再矩阵求和。对于这个模型,不必二维数据结构,可以直接用扫描线在 \(O(N \log N)\)时间内解决。 将所有询问拆成 \([1,l_1-1] \times [l_2,r_2]\) 和 \([1,l_2] \times [l_2,r_2]\) 两个,将矩阵加拆成 \([l_1,l_2,r_2]\) 和 \([l2+1,l_2,r_2]\) 两个,并将它们按行的坐标一起排序。先假设只有一列,即所有 \(l_2=r_2=1\)。按行扫描线过去后,我们对这一列维护两个数字 \(A\) 和 \(B\)。它们要实时保证,如果某一行出现了一个询问,询问的答案就是 \(A \times i+B\) (\(i\) 是行坐标)。所以,对于一个矩阵加,在 \(l_1\) 行时,我们令 \(A+=v,B-=(i-1) \cdot v\)。这样,对于一个 \(l_1 \leq i \leq r_1\) 的询问,答案总是正确的。然后我们在 \(r_1\) 行结束时,令 \(A-=v,B+=i \cdot v\)。表示之后的询问答案不会增多,已经是个定值了。再考虑多列的情况,其实只要对 \(A\) 和 \(B\) 维护一棵区间加,区间求和的线段树即可。
当然,此题还要乘一个项。要把 \(i\) 和 \(j\) 要拆开来,做两次扫描线。这样,如果依然正常地矩阵加,询问并不是简单的矩阵求和了。对于询问 \([l_1,r_1] \times [l_2,r_2]\),我们要统计的是 \(\sum_{j=l_1}^{r_1} Sum(l_2,r_2) \times j\)。其实只要把上述的 \(A,B\) 线段树拓展一下,再加入一棵,实时维护询问时答案是 \(Ai^2+Bi+C\) 的结构。最终复杂度依然是 \(O(N \log N)\),空间复杂度 \(O(N)\)。
此题还会爆LL,但是最终答案在ULL内。虽然容斥时答案会超ULL,但因为ULL自带取模,所以求出的答案依然是对的。
2018 Multi-University Training Contest 5 A
题意:给出一个 \(N(\leq 10^5)\) 个点的边带权的无向图,保证任意两个点之间最多只有两条不相交的路径。求 \(\sum \limits_{s,t,s < t} flow(s,t) \oplus s \oplus t\)。
题解:看起来很不可做的样子。关键是要看出那个奇怪的性质的作用。
可以证明,满足以上条件的图一定是仙人掌(任何一条边都不在一个简单环里)。
这样就简单了。我们形式化地去讨论 \(flow(s,t)\)。转化成最小割。显然一个环里只会割最多两条。且要不是某个环里割两条,要不是割一条树边。而且无论怎样,都可以用调整法证明:如果割的是环里的两条边,有条边必然是环里的最小边。那么我们可以手动”割掉“它,并把它的权值加在环上的其它边。
至此,此图变成了一棵等价的树。\(flow(s,t)\) 即为树上路径的最小边。容易想到根据最小边分治,每次按位计算贡献,把两侧的点统计一下。为了方便维护,可以倒着做:开始每个点不连通;从大到小枚举边,每次连通两块连通块并计算答案。
2018 Multi-University Training Contest 5 G
题意:有一个长度为 \(N(\leq 10^5)\) 的数组,初始时每一个格子都是 \(0\)。有 \(M(\leq 5 \times 10^6)\) 个随机的操作,每次给出 \((l,r,v)\),要求 \(l\)~\(r\) 这些数和 \(v\) 取 \(max\)。求最终的数组状态。
题解:常规的带 \(sort\) \(O(M \log M)\) 的做法是会超时的。考虑怎么优化复杂度。 \(N\) 很小,考虑把复杂度往它上面堆。
要时刻注意 \(max\) 的性质:可以任意结合。即一个操作 \((l,r)\) 总能拆成两个长度是 \(2\) 的幂次的操作。这样总操作次数还是 \(O(M)\),但因为 \(N=10^5\),长度为 \(2\) 的幂次的所有不同的区间只有 \(N \log N\) 个。所以我们可以从大到小枚举那些区间,每次把他们拆解成两个等长的小区间,并且去取max。知道划到每个长度为 \(1\) 的区间。这样复杂度就是 \(O(N \log N+M)\)。
2018 Multi-University Training Contest 3 K
题意:给出 \(N(\leq 10^5)\) 个二维平面的点,任意两个点的距离是它们的点积。求最小生成树。
题解:原来最小生成树还有第三种做法:Boruvka算法。它是一个不断迭代的过程,每次把一些点缩成一个 。每一轮迭代的目标是:对于每一个团,求它与最近的一个团的距离(具体做法是:枚举所有边,如果两侧的点不在团里,就分别更新两个团的值)。然后暴力查看 \(x\) 和 \(g_x\),如果它们不在团里,就合并,并加入这条边的边权(注意,以任意顺序枚举 \(x\) 都是正确的)。容易发现,每一次团的数量至少 \(/2\)(如果把团 \(x\) 和离它最近的团 \(g_x\) 连一条有向边的话,最终每个连通块肯定是环长为 \(2\) 的基环树)。所以该做法复杂度是 \(O(M \log N \alpha N)\)。
Boruvka算法的好处是:容易处理那些点为 \(10^5\),边是隐式的 \(N^2\) 的MST。
本题中,每一轮会有一些连通信息,可以看做每个点有一种颜色。我们要求的是:对于每一个点,找一个和它点积最小但颜色不同的点。
如果没有颜色的限制的点积最小是经典问题。作图后可以发现,备选点落在一个凸壳上;在线查询一个点时,二分一下即可。
有颜色限制怎么办?考虑对颜色进行分治。做到 \([l,r]\) 这些颜色时,计算 \([l,mid]\),\([mid+1,r]\)互相的贡献并继续递归下去。每次把点都归并上来,就可以线性查询点积最小了。这一步是 \(O(N \log N)\) 的。所以总复杂度是 \(O((N \log N+M) \log N)\) 的。
Petrozavodsk Winter 2015 - Michael Tikhomirov Contest 1 D
题意:维护 \(N(\leq 2 \times 10^5)\) 个位置,每个位置或是一个具体的数值,或是一个指向别处的指针(保证指针不成环)。有 \(Q(\leq 2 \times 10^5)\) 个操作:①将一个位置改成一个数值。②设置一个位置的指针。③询问 \(\sum_l^r a_i\),定义 \(a_i\) 是从 \(i\) 一直跳跳到的值。
题解:指针操作看起来是LCT的经典操作。但是询问的那些点在LCT上不连续,很棘手。
其实是分块:经典做法,按询问分块:每 \(O(K)\) 个询问前,\(rebuild\) 一些信息。
把之后涉及到的点都标记成关键点,所以只有 \(O(K)\) 个关键点。预处理询问开始前,所有点跳 \(link\) 跳到的第一个关键点。注意到,在这 \(O(K)\) 个操作中中,它是始终绑定在这个点上的。这样,对于每个关键点开一个 \(vector\),询问区间时,就可以二分出有多少点落在里面了。每次操作时,实时维护关键点之间的有向树;每次询问时,暴力遍历所有关键点,二分计算贡献即可。对于那些一开始不属于任何关键点的点,操作前预处理它们的前缀和,就可以 \(O(1)\) 询问了。
总复杂度为 \(O(N \sqrt {N \log N})\)。
XV Open Cup GP of Tatarstan K
题意:海盗分金币题。有 \(N(\leq 10^9)\) 个海盗分 \(k(\leq 10^9)\) 个金币。每次按顺序制定分配方案,如果至少半数人同意(包括它自己)就分配成功,否则它死亡并递归下一个人继续分配。如果将死亡视为获得负数的金币,所有人都采取这样的策略:尽可能得到更多的金币;有同样多金币时,尽量让别人拿得更少。如果还是有多种决策,随便选一种。有 \(Q(\leq 10^5)\) 个询问,每次问一个编号为 \(q\) 的人能分到的最少和最大的金币数量。
题解:倒着做的思路很明显。首先我们会发现,当 \(N \leq 2 \times K +1\) 时,分法是唯一的:
\(k-\frac{n-1}{2},0,1,0,1,0,\dots\)
从 \(N=2 \times K +2\) 开始就会有多解的情况出现:上一层 \(0\) 的个数大于 \(k\)。我可以任意选定一些人给它 \(1\)。
\(N\) 再变大,每次都会有一段连续的 \(-1\) 产生(此时决策当然唯一),每当到 \(N=2k+2^p\) 时,\(-1\) 会被消光。
所以此题可以设一个递归函数 \(solve(n,k,q)\) 去解。当 \(N\) 较大时,我们可以每次跳过前缀的一段连续 \(-1\),继续递归下一段。复杂度显然是 \(O(Q \log N)\)。
XIX Open Cup named after E.V. Pankratiev. Grand Prix of Eurasia, Division 1 F
题意:长度为 \(1,2,4,8\) 字节的变量分别有 \(k_1,k_2,k_4,k_8(k_1+k_2+k_4+k8 \leq 100)\)个。将其以随机顺序排列,计算struct的实际占用内存(每次放入一个内存为 \(x\) 的变量时,如果之前存了 \(p\) 的字节,要将 \(p\) 扩大成最小的 \(x\) 的倍数;结尾处也要扩大)。求期望内容占用大小。
题解:由均值不等式可得,状态数最多只有 \(25^4\) 个。注意dp时直接维护期望,不要和概率再搅在一起。设计状态 \(f_{S,mod}\) 表示:从内存地址 \(\mod 8=x\) 的地方开始,放入 \(S\) 这些变量(结尾也要填充好)期望的内存大小。转移时,枚举状态 \(S\) 第一个放的变量种类是什么。复杂度 \(O(25^4 \times 4)\)。
XIX Open Cup named after E.V. Pankratiev. Grand Prix of Eurasia, Division 1 G
题意:有 \(N\) 个 \(group\),每个 \(group\) 里有 \(k_i(\sum k_i \leq 10^5)\) 个物品,每个物品有 \(w_i,c_i\) 两种属性。对于每个 \(group\),要不选正好一个物品,要不选正好选两个物品 \((x,y)\),并指定一个 \(\alpha(0 \leq \alpha \leq 1)\),相当于复合出一个配比是 \(\alpha\) 的新物品。要求这个 \(N\) 个物品 \(\sum w_i \leq M\),并使得 \(\sum c_i\) 最小。要输出方案。
题解:首先考虑,同一个 \(group\) 里,那些 \(pair\) 可能会成为一组。对于两个点 \((w_i,c_i),(w_j,c_j)\),它们之间的连线都能取到,而且连线上端的点必然无效(永远也不优)。再仔细分析,可以把点构出一个凸壳,只有凸壳上相邻的点对才可能成为一组。
如果 \(M\) 足够大,肯定是选每一个 \(group\) 里最右边的点。为了适配 \(M\),每次在各个 \(group\) 中找到一个斜率最小的线段,然后把线段右侧的点换成线段左侧的点。开一个堆逐次移动即可。当移动到一半时已经等于 \(M\) 时,就会出现两个点复合的情况。(即复合最多只会出现一次)
2015 ICPC Asia Taipei Regional Contest K
题意:有 \(n\) 个机器人,传送自身所有数据花 \(x\) 分钟;还有 \(m\) 个机器人,传送花 \(y\) 分钟(\(m,n,x,y \leq 1000\))。现在每一个机器人身上都有一个不同的数据信息,以及一个想获得所有数据信息的基站。机器人可以互相传输信息,也可以向基站传输;每次可以传输自身已经获得的所有信息。任何时候,每个机器人只能选择发送和接受中的一个,且不能中断。基站同一时刻也只能接受一个机器人的信息。问达到目标最少需要多少分钟。
题解:先考虑只有一种机器人,那么时间就被划成了 \(x\) 的倍数这些关键点。每次只要基站空着,优先把某个机器人传过去;剩下的机器人两两传输,规模减半。重复这些操作直到剩下一个,再往基站传即可。
有两种时,不妨设 \(x<y\)。显然要尽可能地先把第二种机器人的信息传输完,最后剩下第一种,互相传输的效率就会提高。如果 \(n<m\),每次将某一个 \(y\) 向基站传输,剩下所有 \(y\) 全都找一个对应的 \(x\) 传过去。如此反复,可以使得 \(n \geq m\)。此时,一次性把 \(y\) 传完后,多余的 \(x\) 内部传。然后就重复一种机器人的操作即可。注意此时,时间的关键点是 \(x\) 和 \(y\) 混起来的,可以一点点模拟过去。
2018 ICPC Asia Nanjing Problem L. Lagrange the Chef
题意:给出一个长度为 \(N(\leq 5000)\) ,只含 \(0,1,2\) 的序列。每次可以把一个数换到任意一个地方,消耗单位代价。现在要让 \(1\) 和 \(2\) 都不相邻,问最小消耗代价。
题解:假设我们知道了“拎起来”(去移动)的那些位置的集合。如何判断这种方案是否合法呢?不妨先设固定不动的数中依然存在 \(1\) 和 \(2\),那么所有拎起来的 \(1\) 和 \(2\) 可以直接放在它们边上;所以我们只须让拎起来的 \(0\) 的个数不小于固定的数中 \(1-2\) 交界的数量。
得知了这个判定规则,就可以dp了。设 \(f_{i,j,k}\) 表示选到前 \(i\) 个数,“拎起来的 \(0\) 的个数”与“固定不动的 \(1-2\) 交界数”的差是 \(j\),且最后一位固定的数字是 \(k\) 时的最小代价(即最少拎起来的数)。每次决策当前的数是否拎起来即可。
注意这里还有一些小问题,因为我们之前假设固定的数里必须有 \(1\) 和 \(2\)。如果没有 \(1\),说明 \(1\) 全被拎起来了,我们可以直接贪心出此时的答案;\(2\) 也同理。特判了这两种情况后,我们可以再在 \(dp\) 数组里加上 \(p,q\) 两维,表示是否已经有被固定的 \(1\) 和 \(2\) 了,最后合法状态 \(p=q=1\)。
2018 Multi-University Training Contest 7 K - B - AraBellaC
题意:一个无限串是形如 \(A \dots AB \dots BC \dots C\)(每种字符至少出现一次)的母串重复无限次构成的。现在给出 \(M(\leq 5000)\) 个观测值:第 \(X_i(\leq 10000)\) 的位置是字符 \(ch\)。求母串合法的三元组 \((a,b,c)\) (分别表示这三种字符出现了几次),输出字典序最小的解。有 \(40\) 组数据。
\(a+b+c\) 不会超过 \(10000\)。考虑暴力枚举循环节的长度 \(p\)。\(check\) 其实很简单,每一个位置 \(X_i\) 其实可以映射到 \(X_i \mod p\)。由题目的要求,必须满足 \(\max{A_i \mod p} < \min{B_i \mod p} \leq \max{B_i \mod p} < \min{C_i \mod p}\)。我们要快速求出这些 \(min\max\) 式,就能快速判断并统计答案了。传统上,这个东西可以分块,因为 \(i \mod p=i-\lfloor \frac{i}{p} \rfloor \times p\),只有 \(\sqrt{i}\) 种取值。对于每种取值,对下标 \(i\)的贡献是一条直线,所以至少要 再一个\(log\) 来求每个位置上面所有直线的最小值。复杂度太大。
不妨换一种角度考虑。对于一种求 \(min\max\) 的任务,设 \(F_i\) 表示这种字符在数轴 \(i\) 被观测到过。假设我二分了答案 \(mid\)。我可以每次枚举 \([p \times i,p \times {i+1})\),去\(check\) 这一段里是否存在我期望的位置 \(F_i\),这样复杂度是 \(O(\log ^2)\) 的。进一步的,可以预处理出 \(F\) 向左/向右第一个 \(1\) 的位置,这样就可以省去二分直接找最大最小值,复杂度变为 \(O(N \log N)\)。\(log\) 为调和级数。
2018 Multi-University Training Contest 7 F - Lord Li's problem
题意:给出一个 \(N(\leq 40)\) 位 \(01\) 串 \(T\)。从“正好有 \(3\) 个 \(1\) 的 \(N\) 位 \(01\)串”(显然总共有 \(\binom{N}{3}\) 个)中选出不同的 \(M(\leq 20)\) 个(无顺序)异或起来,使得结果为 \(T\)。求方案数模一个质数。\(50000\) 组数据。
题解:标算竟然是 \(O(NM)\) 的,好厉害呀!显然每一位是对称的,设 \(T\) 中有 \(k\) 个 \(1\),先计算最终有 \(k\) 个 \(1\) 的答案,最后在除掉 \(\binom{N}{k}\) 即可。将 \(N\) 视作常量进行动态规划。
设 \(f_{i,j}\) 表示,已经选了 \(i\) 个 不同 的数(无序),目前异或和里有 \(j\) 个 \(1\) 的方案数。转移第 \(i+1\) 个数时,先不考虑重复的问题。讨论放入的那个数的 \(3\) 个 \(1\)的相对位置(对应本来异或和是 \(0\) 和 \(1\) 的位置分别是几个)。一共有四种情况:\((3,0),(2,1),(1,2),(0,3)\)。直接组合数转移即可。
但是按这样的转移方法,计算出来的 \(f_{i+1,j}\) 是带重复的。即第 \(i+1\) 可能和之前重复。因为重复,相当于白白浪费了两个数来异或,所以直接减掉 \(f_{i-1,j} \times (\binom{N}{3}-(i-1))\) 即可。
同时,对于每一个被转移好的 \(f_{i+1,j}\),每种数字作为第 \(i+1\) 个被转移到都会被计算一次,所以还要除掉 \(i+1\)。
2018 Multi-University Training Contest 7 K - Swordsman
题意:有 \(N(\leq 10^5)\) 只怪兽,每只都有 \(k(\leq 5)\) 维的防御值 \(a_{i,j}\)。再给出一个英雄对应的 \(k\) 维攻击值 \(b_j\)。只有当 \(b_1 \geq a_{i,1},\dots,b_k \geq a_{i,k}\) 时,英雄才能击败第 \(i\) 只怪兽,且每一维攻击值都会受到 \(c_{i,j}\) 的提升。求英雄最多能击败的怪兽数量。
题解:因为打败怪兽不会有坏的影响,所以就是能打就打。麻烦的是,攻击和防御值有 \(5\) 维。
\(5\) 维动态数点显然是不现实的,考虑把条件反向。对于一只怪兽 \(i\),只要 \(\exists j,a_{i,j} \geq b_j\),它就不能被击败。如果对于每一维,分别把怪兽升序排序,那么任何一个时候,每段后缀的怪兽都不能被击败。且这个分界点随着英雄能力的提升会不断往后移动。
所以对于每一个怪兽,维护它目前有 \(g_i\) 维还不合法。每次移动分界点的时候,会把一些怪兽的 \(g_i\) 减一;一旦怪兽 \(i\) 的 \(g_i\) 降为 \(0\),我们可以立即打死他,并尝试继续移动分界点。复杂度为 \(O(Nk \log N)\),\(log\) 是排序。
2018 ICPC 北京 C
题意:求所有三元组 \((a,b,c)(a<b<c,a^2+b^2=c^2,c \leq n)\) 的对数。\(n \leq 10^9\)。
题解:所有 \(gcd=1\) 的三元组,可以充要地转化为 \(\frac{s^2-t^2}{2},st,\frac{s^2+t^2}{2} (s>t \geq 1,(s,t)=1,2 \nmid s,2 \nmid t)\)。即我们要求的是 \(\sum_i \sum_j \lfloor \frac{2n}{i^2+j^2} \rfloor \times [(i,j)=1] \times [2 \nmid s] \times [2 \nmid t]\)。
这个其实挺难搞的。\(gcd\) 只能莫比乌斯反演,反演后是求形如 \(\sum_i \sum_j \lfloor \frac{x}{(i^2+j^2)} \rfloor\)。其中 \(k\) 的取值是 \(1\) ~ \(\sqrt N\),\(x\) 是 \(N\) 能除到的 \(O(\sqrt N)\) 个数。注意,这里可以继续 \(O(\sqrt x)\) 枚举 \(\lfloor \frac{x}{(i^2+j^2)} \rfloor\) 的不同的取值(这样效率约为 \(\int_{1}^{\sqrt n} \sqrt i = n^{3/4}\))。所以我们需要预处理一个 \(F(x)\) 表示 \(a^2+b^2 \leq x\) 的 \((a,b)\) 的对数就可以算出来了。
\(F(x)\) 的计算也大概是 \(O(n^{3/4})\) 的。对于每一个 \(x\),暴力枚举 \(a\),计算对应的 \(b\) 的个数即可。