2023 年 7 月训练记录

训练

7 月没有做题题题题题题题题题。

不想写的题就不写了。

Md5D Many Minimizations#

原问题有个经典做法,首先考虑暴力 DP,fi,j 表示第 i 个数 =j 的最小代价,不难发现 DP 值是个分段函数,然后考虑用堆来维护。

mni=minj{fi,j},每次操作相当于是往堆中先加入两个 ai,然后弹出最大值 mx,可以发现 mni=mni1+mxai

于是,我们发现当 ai<mx 时才会有贡献。计算答案时,我们对每个 ait<mx 分开计算,不难发现,t 的个数 =mxai

我们把 ai<x 的设为 0,将 aix 的设为 1,则就相当于是一个函数 gi 表示堆内 1 的个数。

  1. 0 加入时:

    1. gi1>0,则答案增加 1
    2. gi1=0,则答案不变。
      换而言之,gi=max(0,gi11).
  2. 1 加入时:
    gi=gi1+1

我们发现对 0max 的操作,是我们比较难处理的。

我们把 (i,gi) 看成一个点。我们考虑将对 0max 的位置都先整体向上平移,并要求平移后的路径至少有一个点在 x 轴上,这个限制我们可以通过 y 坐标全部 0 的方案数减去 y 坐标全部 1 的方案数来处理,计算后面的东西可以使用反射容斥来算。

对于 (0,a) 出发,到 (n,b) 结束的路径,我们考虑计算它对答案。首先,总的下降次数为 n+ab2,而由于对 0max 的位置不对答案产生贡献,所以贡献为 n+ab2a=nab2

时间复杂度 O(n2)

记录

AGC015E Mr.Aoki Incubator#

我们先把点按坐标排序,一个点 i 被选中后,能染色在它右侧速度小于 maxj=1ivj 的点,以及在它左侧速度小于 maxj=invj 的点。

所以,越左的点对其左侧影响能力越强;越右的点对其右侧影响能力越强。于是,我们考虑 DP,fi 表示 i 被选中,且 [1,i] 已经全部被染色。因为越左的点对其左侧影响能力越强,如果前 i 个确定了,并且第 i 个被选中了,还有点没被染色,则说明右侧再怎么选也不可能让左侧的点被染色。

对于 fi,可行的转移 j 是一段连续的区间,因为要求 ji 染色能覆盖内部的所有点,所以 j 越大,对其右侧影响能力越强,且区间更小,所以更优。

考虑使用双指针来维护最左的可行转移 j,并用前缀和求出答案。

时间复杂度 O(nlogn),瓶颈在于排序。

记录

P2762 太空飞行计划问题#

最大权闭合子图的板子。

我们让 S 向所有点权为正的点连边,流量为点权,让所有点权为负的点向 T 连边,流量为 点权,原图上的边流量为

正确性:答案为所有正点权和 最小割。首先,最小割不会割原图的边,割 S 到正点权点的边相当于不选这个点,割负点权的点到 T 的边,相当于选了一些正点权的点并由于原题的限制一定要选这个点,导致选了这个点。

构造方案就是 S 能到的点。

记录

[TJOI2015] 弦论#

由于对 SAM 的不熟悉(主要还是因为 10 级就开摆了),再加上我构造法没学明白,导致我一直不会后缀树,然后模拟赛考了。

不过强大 Qiuly、ybw051114 告诉我 SA 也可以建后缀树,于是就来学了下。

source

我们先对原串进行后缀排序,然后求出 height。我们现在处理区间 [l,r],找到区间中 height 最小的位置,将区间分裂,一直递归下去即可得到一棵后缀树。

板子:

Copy
int build(int fa, int l, int r) { int num = ++tot; ::l[num] = l, ::r[num] = r; L[num] = R[fa] + 1; if (l == r) { pos[l] = num; R[num] = n - sa[l] + 1; return num; } int pos = qry(l + 1, r); R[num] = height[pos]; ls[num] = build(num, l, pos - 1), rs[num] = build(num, pos, r); return num; }

感觉这比构造法好理解太多了!!!

有了后缀树做这题就很简单了。

对于 t=0 的问题:我们先后缀排序,然后从前往后每个后缀的 [heighti+1,leni] 的前缀就是按照字典序排好的所有本质不同子串。

对于 t=1 的问题:我们按照上面的方法把后缀树建出来,然后我们在后缀树上遍历一下就可以求出答案了。

CF1221E Game With String#

ZMF 和新疆张克姚 duel 的题。

注意到性质 a>b,如果本来就存在或者能创造出长度为 [b,a) 范围内的连续段,那 Bob 必胜。

然后就做完了。

首先,Alice 获胜要求不能出现长度为 [b,a),并且不能出现超过 1 个长度 2b 的串。

若没有,则直接根据连续段个数决定胜负。

否则,Alice 第一次操作肯定是这个串。我们可以暴力枚举 Alice 的操作方式,如果 Alice 能改变串个数的奇偶性则必胜,否则依旧按照连续段个数决定胜负。

记录

CF603E Pastoral Oddities#

开始看错题了,以为要最小化边权和,直接自闭了。

首先,由于每个点的度数均为奇数,所以连通块大小一定全为偶数。进一步地,我们可以得出只有图中只存在大小为偶数的连通块,就一定能合法。

证明考虑构造。我们随便拉出连通块内的一棵生成树,然后从叶子往上选择断边来调整,因为总数数是对的,所以根一定合法。

于是,我们考虑线段树分治。首先,答案是单调不增的,所以,后面询问用的边前面一定会用。递归到叶子时,如果不满足条件,则把边权把比当前答案大的从小到大加入,直到满足条件为止。

时间复杂度 O(nlog2n),线段树分治和并查集。不过可以用 LCT 做到在线 1log,不过我不会就是了。

记录

CF238E Meeting Her#

•́へ•́╬ 和 DitaMirika duel 的题,他们俩都没过。。 😅。。

注意到当前所在的点一定要求是线路最短路的必经点,但终点则可能是任意的,限制很松。

所以,我们考虑倒过来做。我们记 fii 到终点最少需要乘多少次。我们对每条线路跑一次 dij,以这条终点为起点,求出到每个点所有最短路径中路径中经过最小点权最大值。这个满足不增性,所以可以用 dij 维护,然后对于这条线路上的必经点更新答案。

由于总共之后更新 O(n) 次,每次更新的复杂度是 O(knlogn) 的,所以总复杂度为 O(n2klogn) 的,不过好像正解是 O(n4)

记录

CF1615H Reindeer Games#

保序回归 L1 问题的板子。

我们整体二分,先假设所有数取 midmid+1,求出答案,注意到这是个最大权闭合子图问题,用最小割解决。构造方案是找与 S 连通的部分。

根据论文中的结论,在所有数取 midmid+1 问题中取 mid 的,值一定在 [l,mid],否则值一定在 [mid+1,r]

时间复杂度 O(n2mlogn)=O()

记录

[省选联考 2020 A 卷] 魔法商店#

考虑一个极大的线性基,要求它是所有极大线性基中权值总和最小的。

由于它是极大的,那么任何一个不在这个线性基内的数都可以被这个线性基内的数唯一表示。考虑表示它的数任意删除一个,则就能把它加进去,这是比较显然的,所以它的权值需要比表示它的数中任意一个都要大。

这个条件显然是必要的。如何说明充分呢?我们考虑假设最终加入的一个集合,将他们的权值从小到大排序,依次加入,不难发现,每次权值总和都增加了。因为本来表示它的数都比它小,新选入的数也比它小,所以就不优。

对于权值总和最大的线性基也是同理,所以我们得到了一些偏序关系,只会跑一遍保序回归 L2 就可以了。

保序回归的 L2L1 有一点区别,对于判断 mid,我们是用导数来做,因为 L2 问题的取值不一定是整数。对于边界 L+1=R,由于我们要求整数解,所以我们再按 LR 两种取值来跑。

时间复杂度 O(maxflow(n,nm)logv)=O()

记录

PR1A 删数 QOJ3575 Where is the legend?#

考虑操作的式子本质是将相同的两个差分合并。。。于是,我们令差分数组为 b1,b2,,bn1 考虑把 bilowbit(bi) 的连续段分开来做 DP,并记录 lowbit

注意到合并只会和就乘 2。所以值域是 log2i=1nbi

我们记 gi,j 表示从 i 开始是否可以往后合并成 2j,如果可以,记录合并最后一项的位置。

然后就可以 fi 表示前 i 个数最少能合并成多少段了。

时间复杂度 O(nlogai)

记录

PR10B 打摆#

这都不会。。。/ll 完全没想到可以随,不会交互。。。

首先,我们对于前 5 个点,10 条边,(53)=10,高斯消元(或暴力枚举),得到这些点之间是否有边。

那么,对于后面的点,我们逐个加入,假设当前加入点 i。我们将得到的点随机打乱,得到长度为 i1 的排列 p,然后从前往后扫,假设当前扫到 j。我们询问 (i,pj,pj+1),如果 (i,pj),(i,pj+1) 同时存在或者同时不存在,我们都直接得出答案。否则,我们只能知道这两条边恰有一条存在。我们一直不断往后,后面能推出来时,我们就可以更新前面未确定的了。如果到结束还有一段为确定,要么是整个不确定,那么我们询问第 1 个和第 3 即可;要么是一段后缀不确定,那么我们询问开头和结尾即可。

由于是随机的,所以我们一次询问期望问出 1.5 条边,可以通过。

记录

AGC020F Arcs on a Circle#

注意到有用长度都是整数,所以我们只需要关心线段起点小数部分的大小关系。

由于是离散的,所以我们不需要考虑小数部分相同的情况,并且所有可能的大小关系都是等概率出现的。

我们考虑将最长的线段的左端点作为起点,认为它是 0

选择最长的线段的原因是因为避免这种情况:

img

于是,我们之后枚举左端点的顺序,于是,我们相当于把整个圆变成了 nc 个点。然后从左到右扫描线,记录状态 fi,j,S,表示当前扫到 i,右端点最远到 j,用过的线段集合为 S,由于左端点 i 的线段是确定的,因此只需要枚举它是否在就可以了。

时间复杂度 O(2nn!(nc)2)

记录

[JOISC2022] 京都观光#

考虑现在有两个点 (i,j)(i,j),那么考虑两种方案:

  1. (i,j) 先到 (i,j),再到 (i,j),代价为 (jj)Ai+(ii)Bj
  2. (i,j) 先到 (i,j),再到 (i,j),代价为 (ii)Bj+(jj)Ai

那么,方案一更优,当且仅当 (jj)Ai+(ii)Bj((ii)Bj+(jj)Ai)<0,也就是 AiAiii>BjBjjj

于是,我们求出 AB 的下凸壳,然后每次选更优的走即可。

时间复杂度 O(n)

记录

[USACO21JAN] Minimum Cost Paths#

这题是上一题的一个特殊情况,有特殊的做法,但我们可以继续沿用上题的做法。

我们回顾上述算法的过程,我们对 AB 维护两个指针 i,j,如果 (ai,Aai),(ai+1,Aai+1) 的斜率比 (bi,Bbi),(bi+1,Bbi+1) 大,那就 ii+1;否则 jj+1

由于 n 比较小,所以我们对每个 i 维护 ii+1 时的 j 就可以了。

我们依旧去对 c 求下凸壳,注意到 12,22,32, 是个下凸壳,所以我们只需要求出 c 下凸壳后在 12,22,32, 上二分求出第一个斜率 > 它的位置 pos(其实也可以直接根据导数算),然后查询的时候就对 pos 数组二分即可。

时间复杂度 O(n+qlogn)

记录

UOJ228 基础数据结构练习题#

考虑一次区间加操作只会改变两个位置的差分。考虑区间根号的操作,对于差分不变的位置相当于区间加,所以我们可以直接打 tag

具体实现时,我们当然不用去维护差分。我们只需要对线段树的每个节点维护 min,max,对于区间根号操作到的节点,如果 minmin=maxmax,则直接打上区间加的标记即可。

时间复杂度为 O(nlognloglog(xi+ai))x 操作到 1 的次数是 loglogx 级的。

CF1804G Flow Control#

上一题是本题的 DS 部分的做法。我们先对时间扫描线,我们考虑一段没有时间的区间(也就是没有用户进入、没有用户退出的时间段)。考虑 log 次除 x2 操作后,差分就不变了(不一定全为 0),于是整个序列就进入了循环。

由于奇偶性的原因,差分可能一直为 1,比如 32=1,42=2

维护的过程参考上一题的做法,对于 minmin2=maxmax2 的区间,打上区间加的 tag 即可。

我们只需要不停地对序列进行加到超过限制,整体 x2,一直到 min+1max,并再做一次(或者特判)。再做一次的原因是整体加之后会改变奇偶性,所以这种情况还不确定是最小值为奇数,最大值为偶数的循环状态,还是未循环状态,所以多做一次即可解决问题。当然可以计算加到超过限制最小值的奇偶性,不过不影响复杂度。

时间复杂度 O(nlognlogdi),相当于是每个用户会改变差分 2 次,每次带来 log 次操作,然后每次需要线段树上 log 的查找。

记录

CF1147E Rainbow Coins#

考虑两次询问能够问出所有同色的连续段。

那么,我们只需要再花两次询问问出所有相距 2 的连续段之间是否同色,这样就能确定连续段的颜色了。

于是我们再花两次问 i,i+2

这就就可以 4 次询问解决问题。

记录

ARC161F Everywhere is Sparser than Whole (Judge)#

我们考虑可以对每条边带 1 的权值,对每个点带 D 的权值。于是,问题就转化成了求非空并且不为原图的最大权闭合子图是否 0

首先,如果最大权闭合子图 >0 就直接 NO

做法 1#

然后,官方题解的做法是判断这个图是否强联通,如果非强联通就是 NO,否则为 YES。感觉很有道理,但不会证)

做法 2#

不过,强大 Alex_Wei 在题解中给出了 csy 的做法:

首先,有个结论,如果最小割存在一组最优方案满足割了边 (u,v,w),则跑最大流时这条边一定会被流满,并且 uv 一定属于不同最小割集合(S 集合和 T 集合)。

证明:我们考虑一组割相当于把所有点分成两个点集 AB,并且这两个点集直接的边权总和为最小割的值。那么,在最大流中,这些边一定会流满。否则最大流就小于最小割了。

我们对是否选第一条边分类讨论:

  1. 如果选第一条边,那么只需要判断是否非原图。我们只需要判断是否存在一条边的点不属于 S 集;
  2. 如果不选第一条边,那么只需要判断是否非空。我们只需要判断是否存在一个点不属于 T 集。

时间复杂度 O(ndnd)

我写的是第二种做法。

记录

CF311D Interval Cubing#

感觉很猛啊,很像THUSC2015 平方运算,有一次没过)😅🤡

假设循环节为 n,也就是 a3n1(mod95542721),也就是 3n1(mod9)5542720,然后发现 n=48 可以……

于是,我们只需要对每次数求出 047 的答案就可以了,每次操作就可以 O(48) 地打标记。

时间复杂度 O(48qlogn)

记录

终点#

不会做j交互题题题题题。

考虑先对每个点问一次 1i,设 fi 表示询问 1i 的答案。找到能不断走 fi(不为 0)次数最大的点。

由于 2 是最小不为 1 的数,所以,这个点到 1 的距离一定是 2 的幂,那么就可以找到一条边。

然后,我们就每个点向这条边不断问,得到中点。考虑 BFS,将询问挂到点上,然后 BFS 到点 x 时,再处理 x 的询问,得到点 y 父亲后,再把 y 加入 BFS 队列。由于跳 log 次中点就可以跳到父亲,所以询问次数最大为 n+i=1nlog2(i)

记录

EI 的第六分块#

做法就是首先考虑延续最大子段和的思路,维护 sum,ans,lans,rans,不过区别时,这里维护的是一次函数。

同时,我们多维护一个 t 表示 x 最多增加多少,ans,lans,rans 不变。

每次修改时就递归到所有 tx 的节点,然后更新答案向上 pushup。

感觉 EI 的证明,这个做法的时间复杂度为 O((n+m)log3n+qlogn),其中 m 是修改操作次数,q 是查询操作次数。

记录

ARC164E Segment-Tree Optimization#

赛时看错题了,G!!!

我的做法是考虑能访问到的最底层节点的左端点集合一定是所有区间的左端点和右端点 +1 以及 1 组成的集合。因为这些点是跟它左侧的点被覆盖的区间集合不同,而 1 是一定得有的。

设这个集合大小为 s,于是第一问答案就是 logs

然后考虑计算第二问答案,考虑 DP。令 fi,j 表示前 i 个区间中有 j 个区间被放到上面一层的最小代价。

转移有些细节,需要分当前区间是线段树上的左子树还是右子树讨论下,求出答案。

记录

CF1322E Median Mountain Range#

考虑 01 序列怎么做。为了方便,我们默认 a0=a1,an+1=an。经过讨论,我们发现对于一段区间 [l,r] 满足 al1=al,ar+1=ar,并且 al,al+1,,ar 中间是 01 交替的。

经过讨论,我们发现:

  1. rl+1 为偶数,我们发现是前一半为 al,后一半为 ar
  2. rl+1 为奇数,我们发现最终全变为 al=ar

操作次数都为 rl2

然后考虑不为 01 序列怎么做。我们沿用刚才的做法,我们对值域扫描线,相当于每次对一个位置翻转 01,那么就重新统计下 01 交替的连续段。

注意到对于一个 x 如果将 x 的数视为 1>x 的数视为 0,位置 i 最终 =1 的话,y>x,位置 i 最终 =1。所以,我们只需要在过程中统计每个位置最小的 x 满足最终 =1,这个可以用 set 维护。

记录

AGC017D Game on Tree#

我们考虑 SG 函数。对于一个点 i,假设它的 SG 函数为 fi。由于 i 向上有一条边,随时可以割,所以 SG 值会变。我们考虑实际上相当于是在 DAG 上每个点都向一个终止状态连一条边。

则,原本 SG 函数为 0 的会变成 1,为 1 的会变成 2……

所以,新的 fi=fi+1

注意到子树之间操作顺序无关,所以我们可以视为子树内为独立的游戏。

所以 fx=isonxfi+1

记录

CF1610I Mashtali vs AtCoder#

上一题即为这个题 k=1 的版本。

做这题开始看错题了,看成了换根,结果不久之后,这题出现在了多校。

考虑不在固定点路径的子树 SG 函数都是不变的,现在问题就转化成了求固定点形成的生成树的 SG 函数。

结论:这个生成树的 SG 函数 = 边数 mod2

证明:考虑最终方案,只有 mex 一次会改变一次奇偶性,所以最终的奇偶性是确定的,总共改变 n1 次。

有了这个结论就随便做了,我们每次加入点向上遍历路径,对于未访问的边计算贡献,访问到已访问的边就停止。

时间复杂度 O(n)

记录

CF1746F Kazaee#

VP 时候切了的题。

这种判定性问题一般可以考虑随机化。

首先,每个数出现次数都是 k 的倍数,说明任意一个子集出现次数总和都是 k 的倍数。

于是,我们开始先随机一个 01 序列,表示每个数是否被计算进去。然后,我们询问就检查下这个子集内总出现次数是否为 k 的倍数就行了。

其实不是很会分析正确性,当这个做法跑 30 次就能 AC 了。

不过,交题前想了另一个做法,就是我们给每个数随机一个权值 val,然后查询总权值是否为 k 的倍数,正确性肯定更好,不过上面那个做法直接过了就不管了。

时间复杂度 O(Cnlogn)log 是树状数组的 log,相当小。

记录

CF1746E1 Joking (Hard Version)#

VP 时只过了 E1。

感觉还是相当有意思的。

首先说下我 E1 的做法:

首先,性质是不可能连续两次说假话。

维护当前可能的点集,分成 3 段。先查询 1、2 两段的答案,然后分类讨论:

  1. YES:如果再问一次还是 YES,则说明一定是在 1、2 两端;否则进入情况 2
  2. NO:询问段 2、3,如果为 YES,则分类讨论可得一定在 2、3 段;否则一定在 1、3 段。

于是,我们可以花 23 次询问将集合缩小 13

然后集合大小为 2 时就直接单点问即可。

CF1746E2 Joking (Hard Version)#

再来说下 E2 的做法:

注意到上面的做法其实已经很优了,但是在进入下一层时忽略了之前询问的信息。

我们考虑刻画一般情况,我们设集合对 (A,B),其中 A 表示上一次询问为真话时的答案集合,B 表示上一次询问为假话时的答案集合。假设我当前询问的集合为 pq,pA,qB,再定义 p=Ap,q=Bq

然后根据查询结果分类讨论:

  1. YES

    1. 假设这次说的是真的,那上次可真可假。

      集合 A 变成了 pq

    2. 假设这次说的是假的,那上次一定是真的。

      集合 B 变成了 p

  2. NO

    1. 假设这次说的是真的,那上次可真可假。

      集合 A 变成了 pq

    2. 假设这次说的是假的,那上次一定是真的。

      集合 B 变成了 q

我们考虑用 DP 刻画这个东西。我们令 fi,j 表示 |A|=i,|B|=j,最劣情况下需要多少次查询。

枚举 a=|p|,b=|q|,则 fi,jmax{fa+b,ia,fia+jb,a}+1

这个东西是 n4 的。

于是我们考虑设一个 B。在 |A|+|B|>n 时,直接 a=|A|2,b=|B|2,否则用 DP 处理的最优方案即可。

B20 就可以卡进去了。

时间复杂度 O(ans·n+B4)ans 是查询次数。

记录

CF1827E Bus Routes#

先随便钦定一个根,然后求出每个点所在路径中 LCA 深度最浅的节点,则如果不全为祖先后代关系一定不合法,这两个点肯定不能在 2 条路径之内互相到达。

然后现在,所有这些路径 LCA 深度最浅的节点构成一条链。于是,我们发现,要求所有点都能一步到底深度最深的点,如果可以就合法了。实现的时候以那个点为根跑一遍就可以了。

时间复杂度 O(nlogn)

记录

CF1322F Assigning Fares#

非常厉害的题。

注意到边有 3 种类型:

  1. 父亲和儿子相等,这是没有限制的边;
  2. 父亲 > 儿子,我们称之为 A 类边;
  3. 父亲 < 儿子,我们称之为 B 类边。

首先考虑限制相当于是两条祖先后代的链父亲和儿子大小关系相同,并且相互之间大小关系不同。前者可以先树上差分,然后跟后者用带权并查集维护。

这样,我们就对每条边确定了关系。我们考虑二分答案,单调性是显然的。

假设二分到 k,我们现在去 check。我们对于每个点都求出 fx 表示 x 号点向上的边为 A 类边时,x 权值的最小值。对称的,如果为 B 类边,则最大值为 k+1fx

这并不是代表 x 的权值能在 [fx,k] 之间都能取到,而是在给 fax 更多选择。

那么,我们就对子树内的边分类讨论,假设当前边为 (x,y)

  1. (x,y) 无限制:开摆。

  2. (x,y)(x,fax) 在同一个并查集连通块内,则它的边的类型已经确定了。

    1. 如果权值相同,则为 A 类边,x 权值的取值范围为 [fx+1,k]
    2. 如果权值不同,则为 B 类边,x 权值的取值范围为 [1,kfx]
  3. (x,y)(x,fax) 不在同一个并查集连通块内,则同一个连通块内取值必须自洽,我们分权值为 0 的和为 1 的求出 mx0,mx1

    则可行区间为 [mx0+1,kmx2][mx1+1,kmx0]

    观察下性质,这两个区间要么分别在 [1,k2][k2+1,k],要么同时跨过 k2

    我的做法是维护两个区间,区间 s1[l1,r1] 和区间 s2[l2,r2],初始时,l1=1,r1=k2,l2=k2+1,r2=k,然后每次将 mx0,mx1 排序,于是 mx0<mx1

    那么,我们每次让 s1[mx0+1,kmx2] 取交,s2[mx1+1,kmx0] 取交。

    情况 2 就两个区间都取交。

最后找到最小值就可以了。如果区间为空就不合法了。

构造是相当好做的,我们直接根据转移的 DP 值,对子树打标记表示这个子树要翻转,即 ansikansi+1

时间复杂度 O(nlogn)

记录

posted @   zhaohaikun  阅读(104)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示
CONTENTS