7月杂题

1.CF1835F Good Graph

判定 Yes or No 等同于判是否存在最大匹配。

如果不存在,考虑找到一个不在匹配的左部点,在残量网络上 bfs 即可。

如果存在,考虑 tight 集合是怎么构成的。如果 \(S_i\) 表示包含左部点 \(i\) 的最小 tight 集合,发现每个 tight 集合都是一些 \(S_i\) 的并。

考虑怎么简化 \(S_i\) 的表示。

考虑如果存在边 \((i,j)\) 满足 \(i\in S\)\(i\) 不与 \(j\) 匹配,我们就需要把与 \(j\) 匹配的点加进来。由此能连一张图出来,形式化的,若 \(m_j\ne i\) ,就把 \(i\) 连向 \(m_j\)

\(S_i\) 就是 \(i\) 能到达的点集。现在问题转化成连尽量少的边使新图和原图的传递闭包相同。缩点后在每个 SCC 内连环,然后在 DAG 上存在 \((x,y)\)\((y,z)\) 就删掉 \((x,z)\)

可以 bitset 实现,总复杂度 \(O(n^{2.5}+\frac{n^3}{w})\)

2.CF1753E N Machines

由于答案不超过 \(2*10^{9}\) ,非 \(1\) 的乘法操作显然不超过 \(30\) 个。

我们会在其中选一些移到最后面。注意到对于乘数相同的操作,我们只会选一个前缀。所以可能的方案是不多的,具体的,不超过 \(5000\) 种。

此时可以得到加法操作次数的上界 \(K\) ,我们会选对答案贡献尽量大的到前面。二分第 \(K\) 大的值,对每一段 lower_bound 计算即可。

3. ARC163F Many Increasing Problems

首先得考虑原问题怎么做吧,就是一个 slope-trick,每次在堆里 push 两次 \(a_i\) 再弹掉堆顶,答案就是 \(\sum a_i\) 减掉堆里的数之和。

由于我们只关心最后的和,考虑 \(a=\sum\limits_{x=0}^{+\infty} [x<a]\) ,枚举 \(x\) ,把 \(\le x\) 的看成 \(0\)\(>x\) 的看成 \(1\) ,则我们需要的是最后堆里 \(1\) 的个数。

这个就可以 dp ,转移形如 \(g_{i+1}:=(m-x)f_i,g_{\max(i-1,0)}:=xf_i\) 。这个取 max 是不好处理的,考虑每次如果走到 \(-1\) ,我们就看成把起点往上提高 \(1\)

那现在就变成,我们从任意 \((0,i)\) 出发,有 \(m-x\) 种方案往右上,\(x\) 种往右下,途中必须经过某个 \((x,0)\) 。令最后走到 \((n,i)\) 方案为 \(w_i\) ,则想求 \(\sum iw_i\)

这个是 ez 的了,枚举起点和往上走的次数,利用折线法得到答案,再简化式子即可。

发现最后我们想对每一个 \(i\) 求出 \(\sum x^i(m-x)^{n-i}\) 。直接用二项式定理拆开 \((m-x)^{n-i}\),对每个 \(i\) 求出 \(\sum\limits_{x=1}^{m-1} x^i\) 后即可差卷积计算。算 \(\sum\limits_{x=1}^{m-1} x^i\) 就是算 \([x^i]i!\frac{e^{mx}-e^x}{e^x-1}\)

4. P6256 [ICPC2019 WF] Directing Rainfall

其实是简单题。以前一直不敢写,今天写了发现很简单。首先通过扫描线可以得到线段间的拓扑序,我们从上往下 dp 。

维护 \(f_i\) 表示当前雨的坐标在 \(i\) 需要钻的洞数最小值。则我们需要支持区间加,区间取前缀最小,区间取后缀最小,最后查一遍区间最小。

考虑用线段树维护这个过程,比较难的是后两个操作。

如果一个区间不降/不增,我们就直接当成区间取 min 操作打 tag 。否则就递归做下去。为什么是对的?

考虑一次操作后 \([f_i<f_{i+1}]\ne [f_{i+1}<f_{i+2}]\) 的位置只会增加 \(O(1)\) 个,而我们通过上面的方法保证了,如果位置减少量为 \(k\) ,则复杂度是 \(O(k\log n)\) 的。

总复杂度 \(O(n\log n)\)

5.P9158 「GLR-R4」小暑

直接做是非常难写的,但考虑这个往上合并的过程,我们实际上可以把这个树重构成二叉树!

考虑在新树上 \(p(v)\) 得到的结果为原树中 \(v\) 的子树得到的结果。现在我们要依次合并 \(x,p(v_1),p(v_2),...,p(v_m)\)

就是新建 \(m\) 个点 \(a_1,a_2,...,a_m\)\(a_i\) 左儿子为 \(a_{i-1}\) ,右儿子为 \(p(v_i)\) 。特别的,\(a_1\) 左儿子为 \(x\) 。最后 \(p(x)=a_m\)

这样就把图转成了二叉树,在上面用树剖简单维护即可。

6.CF1446F Line Distance

考虑二分答案,我们想统计不穿过圆的点对数量。

找到每个点对圆的两条切线,形成一段圆弧,则点对合法等同于圆弧相交且不包含。这是二维数点,这个题就做完了。

值得一提的是,我们可以断环为链,对于跨过断点的圆弧,取它的补集显然不影响答案。

7.P7712 [Ynoi2077] hlcpq

要求割点,我们需要优化建图,但不用显式地建出,考虑 tarjan 的时候我们第一需要遍历所有没被遍历的邻点,第二要求所有邻点的 low 的 min。

利用主席树优化建图,以 \(x\) 做扫描线,需要一次加入点,一次删除点。在每个节点统计子树内的点是否全部被遍历,以及被遍历的点 low 的 min 。

现在如果一个点被访问了,我们就需要主席树上修改,但是主席树上怎么修改呢,实际上考虑每个点只会对应主席树上的一个叶子节点,我们直接改变它的信息即可。这样可能使得一些节点的信息不合法,但这并不重要。

因为你考虑主席树上的每个点,它可能因为错误的信息往下递归找点,但每次要么真的找到了点,要么它再也不会往下遍历,所以复杂度是对的。

8.LOJ578. 「LibreOJ NOI Round #2」小球进洞

非常好技巧!转化一下问题,我们需要对子区间做一个括号匹配,要算所有匹配上的括号的权值和。

用线段树维护这个过程,两个子节点经过匹配都是一段右括号+一段左括号的形式,我们需要把靠内的这些括号匹配。

那其实可以把所有剩下的左/右括号的权值和记下来,发现我们合并时只需要在其中一边计算:剩下的左/右括号里前 \(k\) 个的权值和。这个可以直接往下线段树二分,单 log 解决。

(有点类似于楼房重建)

查询也是一样的,不好同时处理剩下左/右括号,考虑处理右括号从左往右,左括号从右往左,就和上面的方法类似了。

10.LOJ3652. 「2021 集训队互测」海胆

枚举 \(r\) 端点,考虑每个限制对 \(l\) 取法的影响。

先考虑“只有一个简单环”,就是用 LCT 维护当前的最大生成树,令最大的不存在树上的边为 \(t_1\) ,次大的为 \(t_2\) ,则我们需要 \(t_2<l\le t_1\)

再考虑“不在环上的点入度不超过3”,这个相当于 \(l\) 有一个下界,而这个下界明显是单调不减的。可能出现问题的情况是,某一刻环的位置发生改变,导致下界突变。

但这是不可能的,考虑环位置发生变化时,\(t_2\) 变成原来的 \(t_1\) ,所以下界一定比原来大。移动下界时我们需要判:全局度数 >2 的点数是否和环上度数 >2 的点数相等。可以通过在 LCT 查链和实现。

现在我们得到了 \(l\) 的上下界。最后我们需要让图连通,不难发现当满足上面两个条件后 点数 \(\geq\) 边数,而连通等同于 点数 = 边数。

所以对每个 \(i\) 维护 \([i,r]\) 的点数减边数。相当于要维护两个序列 \(A,B\),支持:对 \(A\) 区间加;对 \(B\) 查区间和;令 \(S\) 为区间内所有的 \(A\) 取到最小值的位置,对于 \(i\in S\) ,把 \(B_i\) 加上一个数。

这是平凡的。

11.LOJ3695. 「JOISC 2022 Day4」鱼 2

考虑一个鱼什么时候会吃不动了。假设现在它吃了 \([l,r]\) ,那如果 \(\sum\limits_{i=l}^r a_i<\min(a_{l-1},a_{r+1})\) 就吃不动了。我们称之为合法区间。

转化成枚举 \([l,r]\) ,对鱼限制。发现对于这些区间是要么相交要么包含的,且对于相同的端点只有 \(O(\log V)\) 个区间。

先考虑查询,查询就相当于把 \(a_{l-1}\)\(a_{r+1}\) 都修改成 \(+\infty\) ,然后计算 \([l,r]\) 内没有被覆盖的点个数。如果能动态处理出所有合法区间,那个数就是好数的。

修改的时候,考虑所有包含 \(x\)\([l,r]\) 是怎样的。它一定满足 \(a_l>\sum\limits_{i=l}^{x-1}a_i,a_r>\sum\limits_{i=x+1}^{r-1}a_i\)

由此发现可能的 \(l\)\(r\) 都只有 \(O(\log V)\) 的,找到它们,直接两两枚举即可。

12.LOJ3153. 「JOI Open 2019」三级跳

乍一看似乎只能枚举 \(x,y\)\(z\) 。尝试减少可能的 \((x,y)\) 的数量。

不妨对于一个 \(y\) ,考察 \(A_x>A_y\)\((x,y)\) 。那你发现只有最大的 \(x\) 是有用的,如果存在一个 \(x_2<x\) ,那取 \((x_2,x)\) 一定比取 \((x_2,y)\) 优。

\(A_x\le A_y\) 也是类似的了。那现在只剩下 \(O(n)\)\((x,y)\) 了,这个题就可以用线段树计算答案了。

13.LOJ3631. 「2021 集训队互测」学姐买瓜

考虑查询是一个贪心的过程:找到左端点 \(\geq l\) 且右端点最小的区间 \(p\),从 \(l\) 跳到 \(r_p+1\)

这就建出了一棵树,尝试用 LCT 维护。那每次填入一个区间,相当于是对 \([1,l]\) ,把 \(f_i\)\(r+1\) 取 max。

这个没法直接维护,我们重构一下这棵树,对每个 \(f_i\) 相同的连续段 \([l,r]\),对于 \(l\le i<r\) ,从 \(i\)\(i+1\) 连边权为 \(0\) 的边,再从 \(r\)\(f_r\) 连边权为 \(1\) 的边。

这样处理后,每次插入导致的边的改变次数是均摊 \(O(1)\) 的。查询就是 access \(l\) 之后在 splay 上二分 \(r\) 。这个题就做完了。

14.P8497 [NOI2022] 移除石子

这个题很好玩啊。

第一步:思考判定一个序列能不能取完,可以 dp 解决,在状态里记下来:我们取的连续串里,当前有多少右端点 \(i+1\) 且能往后延伸,有多少右端点至少是 \(i+2\)

发现这两个数都只需要 \(\le 2\) 。你就有 10 分了。

第二步:思考初始序列固定,能不能通过放石子变得合法。首先它要求恰好放 \(k\) 个石子,但大多数情况下都等同于:至多放 \(k\) 个石子。可以发现只有几个 corner case 不满足。

仍然沿照上面的 dp ,记下来最少取多少石子,把值域从 \([-1,0]\) 改成 \([-1,k]\) 即可。其中 \(-1\) 代表不能取到这个状态。

第三步:对所有初始序列计数。发现我们确定一个前缀后,只需关心这 \(9\)\([-1,k]\) 的数的值。可以感觉到它们的差能控制在一个常数内,所以可能的状态数是和 \(k\) 呈线性的。

具体的,\(k=100\) 时能遍历到的状态不超过 \(9000\) 种,这个题就做完了。

15.CF1599A Weights

妈的 ISIJ 考了这个题没做起。

考虑把序列从大到小排序后交替分成两部分,倒着做。

如果我们想让大小改变,就删掉最大的数;否则删掉最小的数。

这个题就做完了。

赛时为什么没做起:

想到过倒着做,但因为并没有观察到初始的构造,感觉并没有什么用;然后尝试正着贪心,在讨论的过程中发现了交替放的优越性,但仍有一些情况无法处理。

如果这个时候再去想倒着做就 win 了。

16.CF1495F Squares

首先题意可以翻译成:有一些询问,要在这个图上求两点最短路啊。

画个图瞅瞅就发现特殊边是没有相交关系的啊。

或者说,直接用单调栈来维护,我们可以在弹栈时顺便求出某条边对答案的贡献,用 BIT 维护一下就没了。

posted @ 2023-07-10 23:17  grass8woc  阅读(396)  评论(2编辑  收藏  举报