HDU2022多校联训

2022-07-19

String

\(\text{exkmp}\) 求出 \(S\) 串和它的所有后缀的 \(\text{lcp}\),那么我们令 \([1,n]\)\([i,n]\) 这段 \(\text{lcp}\) 长度为 \(x\) ,当满足 \(i\le x\) 时,对于 \(\forall j,j\times k\le x-i+1\) ,都会在 \((i-1)\times 2+j\times k\) 产生贡献,因此做一个模意义的差分即可。

点击查看代码

Dragon slayer

墙的数量只有 15,爆搜或者状压都能比较轻松的通过。

点击查看代码

Backpack

\(dp[i][j][k]\) 表示前 \(i\) 个物品,异或和为 \(j\),并且体积为 \(k\) 的方案是否存在。

有:

\[dp[i][j][k]=dp[i-1][j][k]\vee dp[i-1][j\oplus w_i][k-v_i] \]

可以用 \(\text{bitset}\) 优化,\(dp[i][j]=dp[i-1][j]\vee(dp[i-1][j\oplus w_i]<<v_i)\)

Ball

考虑枚举一下三个点,我们可以分别计算距离并进行判断。

但这样子时间复杂度太高,考虑枚举两个点,如何确定第三个点,我们即要求其中一条边小于等于这条边,另一条边大于等于这条边这可以利用两个 \(\text{bitset}\) 解决。

点击查看代码

Grammar

Travel plan

由于不存在长度为偶数的简单回路,所以任何两个简单回路不存在公共边,于是这个图就是仙人掌图。

求最大公因数为 \(i\) 的路径,可以用莫比乌斯反演转化为求 \(i\) 的倍数的路径。

这样对只需要对 \(n\) 个只包含 \(i\) 的倍数的边的图计算简单路径数量,仙人掌图上的简单路径数量可以 \(\text{dp}\) 求得。

点击查看代码

Treasure

首先建出并查集重构树(在最小生成树的基础上,每次新增一条边就加一个新点连向合并的两个集合),对于一个询问,我们利用倍增跳到对应的节点上,那么问题就变成了查询一个子树。

那么对于这一棵子树,我们需要查询子树里每种类型的最大值并求和。

因为每种类型的点最多只有 \(10\) 个,我们在重构树的每个点维护子树每种类型最大值的和,那么可见对于一次修改,实际只需要做不超过 \(10\) 次链上加操作,因此只需要像建立一个类似虚树的结构,每次询问从修改点暴力往上跳并且做链上修改即可,这个过程可以用树状数组维护(链上加单点求值在树上差分后变成单点修改子树求和),总时间复杂度 \(O(10\times n\log n)\)

点击查看代码

Path

首先对于上一步是不是特殊边我们可以考虑建一个分层图,上面一层代表上一步是,下面一层代表不是。

注意到如果没有 \(0\) 的边这个题就是普通的最短路。

考虑走到上一层之后我们应该怎么走 \(0\) 的边,我们可以把没访问过的点加入一个 \(\text{set}\) ,并取出所有点并判断这些点是否存在于当前点出边集合,如果不存在就将其最短路更新,更新成功则入堆。

点击查看代码

Laser

首先如果所有点都在同一条水平/竖直/斜线上,那么可以直接输出。

假设我们已经确定一个点在水平方向上(米字的一横),那么随便找一个不在这条直线上的点,用竖线和两条斜线可以交在这条线的三个点上,只需要暴力判断这三个点作为中心点是否合法即可。

对于更普遍的情况,我们只需要每次将坐标旋转 \(45\) 度,将上面的过程重复 \(4\) 次即可,这样可以讨论到所有情况。

或者可以直接找到两个不共线的点,讨论两条线的相交情况,做 \(12\) 次判定也是可以的,时间复杂度 \(O(n)\)

点击查看代码

Walk

Random

答案为 \(\dfrac{n-m}{2}\) ,直接输出即可。

点击查看代码

Alice and Bob

将每个值为 \(i\) 的数字视为 \(2^{n-i}\),那么 \(\text{Alice}\) 的胜利条件就是最终局面中能出现 。

\(\text{Alice}\) 将数字分成两个集合,\(\text{Bob}\) 将其中一个集合减一,就相当于将这个集合中的数全部乘 \(2\),然后将另一个集合删去。

如果 \(\text{Alice}\) 能将集合中的数字按照值二等分,那么无论 \(\text{Bob}\) 怎么操作,黑板上所有数字的总和实际是不变的。

如果集合中的数字总和超过 \(2^n\),由于所有数字都是不超过 \(2^n\)\(2\) 的幂次,那么 \(\text{Alice}\) 的每次分割总能使得两边集合的值均不小于 \(2^{n-1}\)

因此直接判断所有数字的 \(2\) 的幂次的总和即可。

点击查看代码

2022-07-21

Static Query on Tree

树剖或建虚树都可以,标程做法如下:

考虑一个简化的问题 \(1\),如果只有 \(A\) 的限制,也就是求一个集合里所有节点可以走到的节点数。首先对 \(A\) 根据节点在 \(\text{dfs}\) 序中的位置排序,然后将深度加起来,减去相邻节点 \(\text{lca}\) 的深度之和。

在考虑一个稍复杂的问题 \(2\),如果只有 \(A, B\) 的限制。很显然这个问题即两个问题 \(1\) 的交集,但是直接算交集比较困难。我们有公式,两个集合大小之和等于交集大小加并集大小,因此只要算出 \(A, B, A\cup B\) 在问题 \(1\) 的解,就能推断出并集的大小了。

最后就是原问题,其实就是分成了多个子树,在这些子树上进行问题 \(2\) 的操作。

点击查看代码

C++ to Python

签到,只要无视字母、下划线、冒号后输出即可。

点击查看代码

Copy

可持久化平衡树即可,标程做法如下:

一个修改操作对后续的查询操作的影响:如果 \(x\le r\) 就没影响,如果 \(x>r\),相当于查询 \(x-(r-l+1)\),然后去掉修改操作。

因此可以离线,倒着处理所有修改操作,每个修改操作都让它之后的所有 的询问 \(x -= r - l + 1\)

但是这么处理还是 \(O(n^2)\) 的。考虑到我们只要答案的异或和,就有,两个相同的查询可以抵消,因此同一位置至多只会查询一次。这样每个位置用 \(1\) \(\text{bit}\) 的信息表示即可,也就是 \(\text{bitset}\)

我们令 \(\text{dp}\)\(i\) 位为 \(1\) 表示答案需要对 \(a[i]\) 异或。倒着遍历所有操作,如果是查询操作,\(dp[x] ^= 1\) ,如果是修改操作,那么就让 \(r+1..n\) 这些比特右移 \(r-l+1\),代码如下:

	low = dp & (~bitset<N>(0) >> (N - r - 1));
	
	high = dp & (~bitset<N>(0) << (r + 1));
	
	dp = low ^ (high >> (r + 1 - l));
点击查看代码

Keychains

显然关键问题是如何求圆 \(A\) 和 圆 \(B\) 所在平面的两个交点。得到这两个交点后,只要判断是否一个点在圆 \(B\) 内部,一个点在圆 \(B\) 外部(到圆心的距离小于半径、大于半径),就是答案了。

直接算圆和平面交点似乎不太好做,考虑到这两个交点肯定在两个圆所在平面上,因此先求这两个平面的交线,然后求交线和球 \(A\) 的交点(假设球 \(A\) 的圆心和半径就是圆 \(A\) 的半径)。

直线和球的交点的求法,和平面几何的直线和圆交点的求法类似。

点击查看代码

Slayers Come

显然,每个技能都可以击败一个区间的野怪,我们先处理出每个技能可以击败的区间。

先计算区间的右端点:将所有的 \(a[i]-b[i+1]\) 从大到小排序,再将所有的技能按 \(R[j]\) 从大到小排序,依次扫描每个技能( \(R[j]\) 相同的一起处理)。对于 \(a[i]-b[i+1]\ge R[j]\) 的所有 \(i\),则用并查集将 \(i\)\(i+1\) 合并。第 \(j\) 个区间的右端点就是 \(X[j]\) 所在连通块的最右值。

左端点同理。

接下来就是区间重复覆盖计数问题:\(n\) 个位置,\(m\) 个区间,求选出的区间能够重复覆盖 \([1,n]\) 的方案数。

\(dp[i]\) 表示恰好覆盖了区间 \([1,i]\) 的方案数。

我们将所有区间按照右端点从小到大进行排序,依次扫描每个区间,考虑一个区间 对 数组的贡献。

\[dp[r]+ = \sum_{j=l-1}^{r}dp[j] \\ 0 ≤ i ≤ l − 2, dp[i]∗ = 2 \]

用单点加法,区间乘法,区间求和的线段树维护 \(\text{dp}\) 数组即可。

Bowcraft

Snatch Groceries

题目问置信区间重叠前有几个人成功抢到菜。

按关键词为 \(earliest\) 升序排序后,比较相邻两个,如果 \(latiest_i\ge earliest_i\) 则有重叠。

证明。假设前面都没有重叠,那么 \(i\) 之后最有可能和 \(i\) 重叠的一定是 \(earliest\) 最小的,反之如果最小的都没有重叠,那么之后必然不可能有一个区间与 \(i\) 重叠。所以这样排序处理没有问题。

点击查看代码

Keyboard Warrior

使用哈希算法来比较两个字符串是否相同。

我们对字符串进行压缩,把连续相同的字符压缩为 \(\{ch,k\}\) 表示 \(k\) 个字符 \(ch\)

可以用栈来维护当前缓冲区字符。

比较时方便起见,可以将首位和末位独立考虑,如果字符相同数量大于等于目标文本即可。

点击查看代码

ShuanQ

\[P × Q ≡ 1 \bmod M \]

\[P × Q − 1 = k × M, k ≥ 1 \]

\(M\)\(kM\) 的一个比 \(P,Q\) 大的质因子。

最多只有一个质因子满足要求,如果有多个满足要求质因子 \(M_1,M_2\) 那么 \(kM=M_1\times M_2>P*Q\) 矛盾。

点击查看代码

Assassination

DOS Card

动态 \(dp\) 即可。

点击查看代码

Luxury cruise ship

当体积为 \(365\times 31\times 7\) 的倍数时,一定是全取 \(365\) 最优,背包处理出 \(365\times 31\times 7\) 的答案,每次将 \(n\) 分成除以 \(365\times 31\times 7\) 的商和余数,分别处理后加起来即可。

点击查看代码

2022-07-26

Equipment Upgrade

\(dp[i]\) 表示从 \(i\) 升到 \(i+1\) 的期望花费,有:

\[dp[i]=c[i]+(1-p[i])\times(dp[i]+\sum_{j=1}^i\frac{\sum_{t=j+1}^i w_t}{\sum_{t=1}^i w_t}dp[i-j])\\ p[i]\times dp[i]=c[i]+(1-p[i])\times\sum_{j=1}^i\frac{\sum_{t=j+1}^i w_t}{\sum_{t=1}^i w_t}dp[i-j]\\ dp[i]=\frac{c[i]}{p[i]}+\frac{1-p[i]}{p[i]}\times\sum_{j=1}^i\frac{\sum_{t=j+1}^i w_t}{\sum_{t=1}^i w_t}dp[i-j]\\ \]

可以分治 \(\text{NTT}\) 求出,\(\sum_{i=0}^{n-1}dp[i]\) 即为答案。

点击查看代码

Boss Rush

二分答案,状压 \(dp\) \(\text{check}\)

点击查看代码

Cyber Language

小模拟

点击查看代码

Divide the Sweets

Spanning Tree Game

状压连通性,做背包,时间复杂度 \(O(m^2Bell(n))\)\(Bell(n)\) 表示 \(n\) 的拆分数。

点击查看代码

Dusk Moon

对于一个点集,它的凸包覆盖住了所有点,且最小覆盖圆覆盖住了凸包,因此仅保留凸包的顶点不会影响答案。

由于点的坐标在给定的正方形范围内随机,因此一个点集的凸包的期望顶点数为 \(O(\log n)\) ,使用线段树直接记录区间凸包点集,然后对于 \(O(\log n)\) 个点运行最小圆覆盖算法即可。

时间复杂度 \(O\left(q \log ^{2} n\right)\)

点击查看代码

Shallow Moon

Laser Alarm

三个不共线的点可以确定一个平面。对于任意一个平面,将其调整至经过三个顶点,结果不会变差。因此枚举三个顶点得到平面,然后 \(O(n)\) 计算触碰了该平面的线段数,更新答案即可。所有点都共线的情况需要特判。

时间复杂度 \(O\left(n^{4}\right)\)

点击查看代码

Package Delivery

考虑 \(r\) 最小的那个区间 \(k\), 第一次取快递放在第 \(r_{k}\) 天一定不会使结果变差。此时可能有很多区间覆盖了 \(r_{k}\), 那么为了尽量延后下一次取快递的日期, 此时的最优策略应该是选择覆盖 \(r_{k}\)\(r\) 值最小的 \(k\) 个区间, 使用堆找到并去掉这些区间后, 问题就递归了。重复上述过程直至处理完所有 \(n\) 个区间。

时间复杂度 \(O(n \log n)\)

点击查看代码

Range Reachability Query

时限比较大, \(n,q\) 比较小,考虑 \(\text{bitset}\) ,令 \(dp[i][j]\) 表示从点 \(i\) 出发是否能到达询问 \(j\) 的答案,\(S[i][j]\) 表示边 \(i\) 是否能在询问 \(j\) 中使用,对于一条边 \(u_i\to v_i\) 有转移:\(dp[u_i]|=dp[v_i]\&S[i]\)

其中 \(S\) 可以扫面线求出,不过如果暴力存下每一个 \(S\) ,空间有些不够,可以分块,只存 \(\sqrt n\) 个关键点的 \(S\) ,每次用的时候从关键点处递推,时间复杂度 \(O(\frac{mq}{w}+m\sqrt m)\) ,不是复杂度瓶颈。

点击查看代码

Taxi

如果没有 \(w\) 的限制, 那么是经典问题。根据 \(|x|=\max (x,-x)\) ,有:

\[\begin{aligned} & \max \left\{\left|x^{\prime}-x_{i}\right|+\left|y^{\prime}-y_{i}\right|\right\} \\ =& \max \left\{\max \left(x^{\prime}-x_{i},-x^{\prime}+x_{i}\right)+\max \left(y^{\prime}-y_{i},-y^{\prime}+y_{i}\right)\right\} \\ =&\left.\max \left\{x^{\prime}-x_{i}+y^{\prime}-y_{i},-x^{\prime}+x_{i}+y^{\prime}-y_{i}, x^{\prime}-x_{i}-y^{\prime}+y_{i},-x^{\prime}+x_{i}-y^{\prime}+y_{i}\right)\right\} \\ =& \max \left\{\left(x^{\prime}+y^{\prime}\right)+\left(-x_{i}-y_{i}\right),\left(x^{\prime}-y^{\prime}\right)+\left(-x_{i}+y_{i}\right),\left(-x^{\prime}+y^{\prime}\right)+\left(x_{i}-y_{i}\right),\left(-x^{\prime}-y^{\prime}\right)+\left(x_{i}+y_{i}\right)\right\} \end{aligned} \]

分别记录 \(x_{i}+y_{i}\)\(x_{i}-y_{i}\)\(-x_{i}+y_{i}\)\(-x_{i}-y_{i}\) 的最大值即可在 \(O(1)\) 时间内求出所有点到 \(\left(x^{\prime}, y^{\prime}\right)\) 的曼哈顿距离的最大值。

现在考虑加入 \(w\) 的限制。将所有城镇按照 \(w\) 从小到大排序, 并记录排序后每个后缀的 \(x_{i}+y_{i}\)\(x_{i}-y_{i}\)\(-x_{i}+y_{i}\)\(-x_{i}-y_{i}\) 的最大值, 用于 \(O(1)\) 求给定点 \(\left(x^{\prime}, y^{\prime}\right)\) 到该后缀中所有点的距离最大值。

选取按 \(w\) 排序后的第 \(k\) 个城镇,\(O(1)\) 求出给定点 \(\left(x^{\prime}, y^{\prime}\right)\) 到第 \(k . . n\) 个城镇的距离最大值 \(d\) ,有两种情况:

  • \(w_{k}<d\) ,那么第 \(k . . n\) 个城镇对答案的贡献至少为 \(w_{k}\) 。用 \(w_{k}\) 更新答案后,由于第 \(1 . . k\) 个城镇的 \(w\) 值均不超过 \(w_{k}\) ,因此它们不可能接着更新答案, 考虑范围缩小至 \([k+1, n]\)

  • \(w_{k} \geq d\) ,那么第 \(k . . n\) 个城镇对答案的贡献为 \(d\) 。用 \(d\) 更新答案后, 考虑范围缩小至 \([1, k-1]\)

容易发现每次考虑的范围都是一个区间, 如果每次取 \(k\) 为区间的中点, 那么迭代 \(O(\log n)\) 次即可得到最优解。

时间复杂度 \(O((n+q) \log n)\)

点击查看代码

Two Permutations

首先特判序列 \(S\) 中每个数字出现次数不都为 \(2\) 的情况, 此时答案为 \(0\)

动态规划,设 \(f_{i, j}\) 表示 \(P\) 的前 \(i\) 项匹配上了 \(S\),且 \(P_{i}\) 匹配 \(S\) 中数字 \(P_{i}\)\(j\) 次出现的位置时,有多少种合法的方案。由于 \(S\) 中每个数字出现次数都为 \(2\) , 因此状态数为 \(O(n)\) 。转移时枚举 \(P_{i+1}\) 匹配哪个位置, 那么 \(P_{i}\) 匹配的位置与 \(P_{i+1}\) 匹配的位置中间的那段连续子串需要完全匹配 \(Q\) 中对应的子串, 使用字符串 \(\text{Hash}\) 进行 \(O(1)\) 判断即可。

时间复杂度 \(O(n)\)

点击查看代码

2022-07-28

区间 \(DP\),设 \(f_{i, j}\) 表示 \([i, j]\) 为合法括号序列且 \(i, j\) 上括号相互匹配的方案数,\(g_{i, j}\) 表示 \([i, j]\) 区间形成一 个合法括号序列的方案数,转移为:

  • 枚举 \(i, j\) 位置上填写的内容,如果形成匹配的括号对,则:\(f_{i, j}=k * g_{i+1, j-1}\) ,其中 \(k\) 为使得 \(i, j\) 上括号相匹配的方案数。

  • 一般地,\(g_{i, j}=g_{i, k}+f_{k+1, j}\)

答案取 \(g_{1, n}\) 即可,复杂度 \(O\left(n^{3}\right)\)

点击查看代码

在最短路图上跑最长路。

  • 先用 \(\text{dijkstra}\) 在第一个权值上跑出最短路图来,并求出第一个答案(最短路图的边权为第二个权值)。

  • 注意到第一个权上可能为 \(0\) ,因此它并不一定是个 \(\text{DAG}\),需要用 \(\text{trajan}\) 将强连通分量缩起来。

  • 获得了 \(\text{DAG}\) 之后,只需要在 \(\text{DAG}\) 上求最长路即可得到第二个答案。

点击查看代码

Magic

输出一堆 \(No\) 即可。

证明:

对于一个合法的解,应当满足不存在同时包含 \(0,1,2\) 的三角形,下面我们证明这样的三角形一定存在。

左下角必然是 \(1\) ,右下角必然是 \(0\) ,底边不能含有 \(2\),则底边上必然有奇数条 \(1-0\) 的边,这些边都属于一个小三角形。考虑其他的 \(0-1\) 边,由于不在两个斜边上,其他的 \(0-1\) 边必然属于两个三角形。因此 “每个三角形内 \(0-1\) 边的数量" 的和必然为奇数。

但是,假设不存在 \(0-1-2\) 的三角形,则所有三角形都必然包含 \(0\) 条或 \(2\) 条的 \(0-1\) 边,产生了矛盾。

因此一定存在 \(0-1-2\) 的三角形。

点击查看代码

BIT Subway

签到题,阅读理解题。

真实的情况很容易算,\(DLee\) 的价格实际上是一个关于总原票价 \(x\) 的分段函数:

\[\text { ans }=\left\{\begin{array}{ll} x & 0 \leq x<100 \\ (x-100) * 0.8+100 & 100 \leq x<225 \\ (x-225) * 0.5+200 & 225 \leq x \end{array}\right. \]

点击查看代码

Climb Stairs

由于题目要求必须把所有怪物打完,所以跳过的怪物还必须得走回去打败才行。

我们要从当前位置 \(x\) ,找到一个右端点 \(r\) ,使得可以按照 \(r, r-1, r-2, \ldots, x+1\) 的顺序打败这一段的怪物。

不难看出 \(r\) 更小的时候不会更劣。直接暴力维护当前想要先到达的右端点(满足 \(x+k \leq r\) ),用线段树维护一下 \([l, r]\) 的更新位置后,相当于实际上完成了击杀 \(r, r-1, \ldots, l\) 的过程,所以将后面的区间加上相应的值。由于每个右端点只会被计算一次,所以时间复杂度是 \(O(n \log n)\) 的。

点击查看代码

Fight and upgrade

Fall with Full Star

Fall with Intersection

posted @ 2022-07-20 11:37  一粒夸克  阅读(119)  评论(0编辑  收藏  举报