0621-0622 杂题

本次的题目对码力有一定的考验,所以会将一些

ABC116D

我们发现,\(t\) 对答案的贡献是“不同的种类个数的平方”。这个东西很明显很难用数据结构去维护,所以我们的暴力应该花在这上面而尽量去维护 \(d\) 的贡献。

考虑枚举“至少选择的种类个数”下的最大结果,设它为 \(x\)。那么就至少要选择 \(x\) 种不同的寿司。而剩下的其他种类,选不选无所谓。即使选了,当前答案一定变得不会比最优解更优,且一定会在后面被统计倒。

那么,在限定种类个数的条件下,我们记录每个种类中最大的 \(d\),然后将所有种类按照这个排序,前 \(x\) 个种类的最大值选上,然后剩下的再选择最大的 \(k-x\) 个。

如何用数据结构维护它呢?我们可以巧妙的使用 set。我们用两个 set,一个是所有种类的贡献,一个是已经被加入的数。我们发现,新加入答案集合的数,一定是以“种类的最大数”的形式加入,因为“剩余数”只会随着名额的减小而越来越卷。

所以,我们先一遍处理出前 \(k\) 个数,然后把所有“当前种类的最大数”压进集合里。每次找到最大的最大数,判断其是否已经被选中。已经选中,答案不会有任何影响。没有被选中,弹出附加集合中最小的,把当前的选进去。

ABC114C

首先考虑状压 \(dp\),设 \(dp_{i,j,msk}\) 表示当前 \(dp\) 到第 \(i\) 位,是否可以随便填不考虑上限,\(3,5,7\) 是否分别已经出现过的方案数。

这样,转移就需要讨论:

在可以填 \(3,5,7\) 的情况下,我们分别判断三个是否可行。如果 \(a_i>x\) 或者 \(j=1\),就可以填,并且后面都是 \(j-1\)。否则如果 \(j=0\)\(a_i=x\),可以填,但是 \(j\) 依旧是 \(0\)。如果 \(a_i<x\) 就不能转移。

但是这样的麻烦很多,我们的数字不承认前导 \(0\),所以我们必须枚举所有的开始位置,然后讨论在这一位如何开始是否可以随便转移。

考虑观察性质,我们发现,这道题根本不用 \(dp\),因为方案的总数一共只有 \(3^{10}\) 种。所以我们完全可以从 \(0\) 开始枚举,每次在原来的数尾巴后面加上一个数,省去前导 \(0\) 的麻烦。

这样,我们用 \(dfs\) 就解决了。

ABC207F

考虑树形 \(dp\)\(dp_{i,j,k}\),当前在第 \(i\) 个节点,第 \(i\) 个节点的子树中有 \(j\) 个被监视的点,\(k\) 是记号,\(0\) 表示没有被观察,\(1\) 表示被观察但没有观察者,\(2\) 表示有观察者。

然后我们从每个节点的所有儿子进行 \(dp\),先把当前节点设为“有/无观察者”两种状态,对应的 \(j\)\(1\)\(0\),对应的 \(k\)\(2\)\(0\)

重头戏是转移,转移比较复杂,每次我们将当前的状态和子树的状态相结合。其中,子树是 \(2\) 且当前是 \(0\),会增加一个当前节点被监控,并转移到 \(1\)。子树是 \(0\) 且当前是 \(2\),会增加一个儿子节点被监控。其他的转移,被监控节点数量就是两边数量之和。且只有第一个转移会改变当前节点的状态,其他都是不变。

然后是复杂度分析,乍一看,每个儿子都 \(O(n^2)\) 枚举,好像是 \(O(n^3)\) 的。但是实际上,我们发现,因为子树大小的限制,其实我们枚举“被观察节点的数量”是不能超过 \(size_x\) 的。而每次转移,就是把当前子树枚举 \(sz_x\) 次,分别和前面的所有子树 \(\sum sz_y\) 合并一次。如果将其等效为在左右各枚举一个点,我们发现每个点对都只会在它们的 \(lca\) 被枚举到。

所以,我们发现,转移的总次数是 \(O(n^2)\) 的,复杂度也是 \(O(n^2)\)

ABC136F

考虑将每个点集包含的点数转为统计每个节点在哪些点集下会被统计到。

考虑正难则反,我们统计所有的不能覆盖当前节点的点对。我们发现,如果点集没有任何点,不会覆盖当前点。否则当且仅当被选中的所有点都在当前节点的严格上/下/左/右。

这就启示我们对每个点,统计严格在它左边、右边、上面、下面的点,并减去只选它们的方案数。但是这样会算重,所以还需要加上左上/右下/左下/右上的方案数。这就很麻烦了,因为变成了两个条件,是一个二维属点问题。难道我们还要写树套树吗?

考虑离线。我们离散化 \(y\) 轴(原来的坐标对答案没有影响,可以直接覆盖坐标),然后建立树状数组。离线下来,从左到右扫一遍,扫描途中记录左、左上和左下的贡献。从右到左再扫一遍,记录右、右上和右下的贡献。然后上下的贡献就不需要离散化然后树状数组了,直接排序跑一遍即可。

注意,处在同一列不能算作左,所以所有 \(x\) 相同的点需要统一处理答案,然后统一进行贡献。

最后得到每个点被包含的方案数,加和得到总方案数。

ABC130F

我们发现,对于所有运动方向相同的点,只有最左、最右、最上、最下四个极值有用,因为大家的相对位置不变,所以极值也一直相同。

然后我们考虑某一个固定方向,假设我们要求的是 \(\max\)。那么实际上会贡献的只有三个点:运动方向和当前方向相同的点中,最趋近当前方向的。运动方向和当前方向垂直的点中,最趋近当前方向的。运动方向和当前方向相反的点中,最趋近当前方向的。

假设我们可以往回运动,也就是时间轴可以为负(省略分类讨论的麻烦),那么一定是这样的:一开始,最大值是和当前方向相反的点,它是一个斜率为 \(-1\) 的一次函数。然后,最大值是和当前方向垂直的点,它是一个常数。最后,和当前方向相同的点到了最前面,这就是斜率为 \(1\) 的一次函数。

而这是建立在三种点都有的情况下。如果某种点没有,就直接忽略。而也有常数值当不了最大值的情况,直接删掉常数这一段即可。

所以每个坐标的答案就变成了最多 \(3\) 段一次函数。并且 \(k\in\{-1,0,1\}\)

我们把时间依次断开,对于所有时间段,找出这段时间内各个方向的最大值函数,乘出一个二次函数,顶点找最值即可。

但是这道题的难度在实现。首先,坐标不同,有的要 \(\min\) 有的要 \(\max\),难道写四遍吗?

我们可以分别给上下左右编号 \(\{0,1,2,3\}\) 这样 \(x\) 的相反方向就是 \(x\oplus 1\)。然后我们发现,最小化 \(x\) 再取负其实就是取负然后最大化。所以我们统一了四个方向的形式,最大化当前坐标,只不过负方向的两个要把所有坐标取反。

然后考虑值域,首先,二次函数的 \(a\) 不超过 \(4\)\(b\) 不超过 \(2e8\)\(c\) 不超过 \(1e16\),所以代什么值进去都不会爆 long long,即使都翻两倍也不会有问题。然后就是精度问题。我们发现,因为唯一会炸整数的就是 两个斜率分别为 \(1\)\(-1\) 的一次函数的交点,只会是 \(0.5\) 级别的小数。为了这一点去搞一堆小数离散化什么的实在不值得。还记得我们前面说翻两倍也不会有问题吗?我们干脆把所有的坐标都翻两倍,这样所有的时间区间也都是整数,离散化统计方便,最后输出答案除以 \(4\) 就好了。

ABC135F

考虑将 \(s\) 复制 \(x\)\((x>2)\),然后 \(t\) 的循环可以完全覆盖中间的某一个完整的 \(s\),那么根据循环节中“交错循环节”相关的结论可以知道,这时 \(t\) 的循环一定可以继续覆盖 \(s\) 的循环,答案就是无穷的。

所以,只要 \(t\) 可以完全覆盖循环 \(s\) 中的一段 \(s\) 就可以了。我们可以先将 \(s\) 循环直到 \(>t\),然后循环三次,然后判断是否存在一个覆盖中间一段的子串为 \(t\) 的循环。这个可以用 \(hash\) 解决。不过它只能判断是否无穷,还是要和下面的结合起来,所以没有太大优势。

或者,我们可以用确定性算法。首先,为了计算方便,我们把 \(s\) 扩张 \(4\) 倍。如果 \(t\) 可以覆盖一个 \(s\) 节,一定能覆盖另一个。所以如果我们找到的最长的 \(t\) 循环次数使得这个循环 \(t\) 串已经长度达到了 \(2|s|\),也就可以肯定它包含了一个中间串,那么就是无穷的。

所以,我们二分答案,二分出最长的 \(t\) 是循环次数 \(x\) 使得循环 \(x\) 之后 \(t\) 依旧是 \(4s\) 的子串。这一过程可以用 \(kmp\) 做到线性判断和确定性判断。然后判断得到的长度是否超出了限制,如果是,那么就一定可以了。

但是,我们其实也可以只循环 \(s\) 两次,因为上面我们的做法本质是利用了抽屉原理,但是实际上忽略了可以循环匹配,也就一定可以首位拼起来然后直接匹配。而重复两遍的本质就是破环为链。

官方题解似乎是图论做法,但是倒腾了好久没看懂翻译的日语。

ABC135E

方法一:函数法

首先,如果 \(k\) 是偶数且 \(x+y\) 是奇数,明显是不可以的。

那么,我们考虑最大范围的跳,也就是每次都往一个方向,不往回跳。这样 \(t\) 次跳跃之后来到的就是所有与 \((0,0)\) 曼哈顿距离为 \(tk\) 的点。

然后,我们考虑 \((x,y)\) 跳一次的范围,显然是由四个一次函数围成的一个矩形。而我们的大矩形也是由一次函数围成的。

那么,考虑扩张大矩形直到当前矩形的边和小矩形产生交点。如果交点在整点,那么就可以直接得到答案了。先从 \((x,y)\) 跳到交点,因为每一步都是极大跳跃,所以这部分的构造是容易的。

但是麻烦的是另一种情况,也就是交点不在整点。

我们考虑交点不在整点本质上是什么,本质上其实是当 \(k\) 是奇数的时候,步数的奇偶性是确定的。如果和目标奇偶性不同,就必须多一步以平衡奇偶性。那么我们假设当前的交点是 \((x,y)\),考虑如何平衡奇偶性。

第一种:如果当前线和小矩形有交点,那么在形内一定有整点的交点。这些点的和的奇偶性,因为斜率是 \(1\),横纵轴同时改变,所以奇偶性依旧和交点是一样的。但是这样就允许我们用两步完成之前想要一步做的事情。因为当前点和目标点的曼哈顿距离不超过 \(k\),所以可以再画两个矩形找交点,因为此时奇偶性改变已经平衡了,所以交点一定在整点上,直接构造输出即可。

第二种:我们发现,一条线将小矩形分成两半,必然有一个顶点在大矩形内部。而这个点的奇偶性和目标点的奇偶性是相反的,需要的步数也是相反的。这样我们又得到了一个需要配平的目标点,但是最长线少了一个。这样我们就可以一路倒推回去,直至目标点落在单位 \(1\) 的大矩形上。

方法二:

先假设 \(x,y\) 是正的,如果不是就在输入和输出处全部取反。

假设答案一共走了 \(n\) 步,那么我们总共跨越的距离就是 \(nk\),首先要有 \(x+y\le nk\)。然后假设其中有 \(a\) 个正贡献,\(b\) 个负贡献。那么就有 \(a+b=nk\)\(a-b=x+y\)。直接枚举 \(n\) 然后解出 \(a,b\),判断是否可行即可。

但是最终还要构造。其实我们发现烦人的只是 \(b\),只要我们集中把负贡献处理掉,就可以了。我们可以每次逆向移动离答案最近的坐标,这样可以保证我们的东西是均摊的,如果我没有解别的方案也一定不会有解。移动到 \(b=0\),也就是每一次都是极大跳跃且不回头,就很好构造了。

是码量最小的做法。

方法三:

先切比雪夫,然后发现,我们就是要每次给 \(x\)\(y\) 坐标 \(\pm k\),另一个随意,只要绝对值不超过 \(k\) 即可。

那么就是在跳正方形了,比曼哈顿距离的倾斜正方形而言,要好做很多。这时候,我们可以把每个的移动拆成若干个 \(\pm k\) 和一个小于 \(k\) 的运动。然后我们可以发现,最多只有两次是往回跳的(平衡奇偶性)。也就是前面的跳跃都是极大跳跃,就钦定它是第一步和最后一步。我们就可以枚举第一次是 \(x\) 运动 \(k\) 还是 \(y\) 运动 \(k\),然后另一个的变化量满足新起点和新目标点坐标差之和为 \(k\) 倍数。因为可以取 \([0,k]\) 任意值,所以一定可以实现。都搞出来之后找出步数最少的方案输出即可。

posted @ 2023-06-23 01:16  jucason_xu  阅读(12)  评论(0编辑  收藏  举报