联合省选 2021 B 卷题解

Day1

数对

给定 n 个正整数 ai,请你求出有多少个数对 (i,j) 满足 1in1jnijaiaj 的倍数。

2n2×1051ai5×105

考虑使用桶,记 cntx 表示 ai=x 的个数。

那么分两种情况讨论,第一种情况是 ai=aj=x,对答案的贡献为 (cntx2);第二种是 ai=x<aj=y,那么这时候枚举 ai 的值 x,同时枚举 x 的倍数 y,对答案的贡献为 xycntxcnty

时间复杂度是经典的调和级数 O(n1+n2+n3+)=O(nlnn)

卡牌游戏

n 张卡牌,第 i 张卡牌的正面有数字 ai,背面有数字 bi,初始时所有卡牌正面朝上。

现在可以将不超过 m 张卡牌翻面,最小化朝上的 n 个数字的极差。

3n1061m<n1ai,bi109ai 单调不下降,2n 个数字互不相同。

先把 a,b 拼成一个长度为 2n 的数组 c 排序。

对于这个有序的数组,极差即是选中的那一段 l,rcrcl

于是用双指针枚举 l,r,不在 l,r 当中则意味着那一位被删除,具体要求是:

  • 删掉的 a 面不超过 m
  • 不存在同一张卡牌的 a,b 面同时被删除。

对于第一条开一个 cnt 维护,第二条开一个 vis 数组维护即可。

时间复杂度 O(nlogn),不明白 a 有序有什么意义。

图函数

对于一张 n 个点 m 条边的有向图 G,定义函数 f(u,G)

  • 初始化返回值 cnt=0,图 G=G
  • 1n 按顺序枚举顶点 v,如果当前的图 G 中,从 uv 与从 vu 的路径都存在,则将 cnt+1,并在图 G 中删去顶点 v 以及与它相关的边。
  • 2 步结束后,返回值 cnt 即为函数值。

现在给定一张有向图 G,请你求出 h(G)=f(1,G)+f(2,G)++f(n,G) 的值。

更进一步地,记删除(按输入顺序给出的)第 1i 条边后的图为 Gi,请你求出所有 h(Gi) 的值。

2n1031m2×1051xi,yin,没有重边和自环。

因为只要求求出每个 h(Gi),而不是求具体的 f(u,Gi),所以考虑贡献法。

考虑一对 (u,v) 如果能对 f(u,Gi) 造成贡献,当且仅当存在一条 uvu 的环,且这个环上没有编号 <v 的点。

于是问题转化为对于 Gi,求 Gi 中有多少 (u,v)uv)满足存在 uvu 的环不经过编号 <v 的点。

一个点对显然会对一个 G 的前缀造成贡献,令 path(u,v) 表示最大化的 uv 的路径上经过的边的编号的最小值。那么 G1min(path(u,v),path(v,u)) 会得到贡献。

可以直接 Floyd O(n3+m) 或 Dijkstra O(nmlogm) 求出。

当然这不稳,可以考虑一个更高明的做法。枚举 v,在每张图中只保留 [v,n] 那些点,求出每张图中它能到达的点的个数即可。

当然直接这样模拟是 O(nm2) 的,考虑反转时间轴变成逆序加边,对于一条新加的边 (a,b)a,bv):

  • 如果 visa=1visb=0,那么从 b 开始 BFS;
  • 如果 visa=0visb=0,那么先加到图中,等着以后可能有用;
  • 否则这条边没有意义。

易证每一条边最多只会用到一次,所以在 BFS 的时候“过河拆桥”即可。时间复杂度 O(nm)

Day2

取模

给定 n 个正整数 ai 请你在其中选出三个数 i,j,kijikjk),使得 (ai+aj)modak 的值最大。

3n2×1051ai108

首先将 a 数组排序,逆序枚举 ak,在前面做二分或者双指针求出 (ai+aj)modak 的最大值更新答案。

ansak 的时候就可以 break 了,可以证明枚举的 ak 的个数是 log 级别的,但我不会证

宝石

给定一棵大小为 n 的树以及 m 种宝石,结点 i 上有第 wi 种宝石。

宝石收集顺序是一个长度为 c 的序列 PP 中没有重复元素。

q 次询问,每次给出 s,t,问从 s 走到 t 的过程中,所经过的结点的 w 形成的序列与 P 的最长公共子序列的长度。

1n,q2×1051c,m5×1041Pi,wim

st 拆为 slca,lcat 的两个过程。

考虑链上的情况,记结点 u 的后继 sucu 为其右边最近的满足 wvP 序列中恰好是 wu 的下一项的 v

那么如果询问的 s<t,就从 s 右边的第一个 w=P1 的位置开始,不断跳 suc,直到越过 t 结束,跳的次数就是询问的答案。不难发现这个过程可以倍增优化。

现在搬到树上,slca 的过程不难套用上述方法,但如果考虑 lcat 呢?

一个解决办法是把过程拟过来,记录 preu 为其父亲链上的最近的满足 wvP 序列中恰好是 wu 的前一项的 v

每次询问的时候二分答案 a,从 t 上方的最近的 w=Pa 的那一个位置开始不断跳 pre 就行了。

至于找到“t 上方的最近的 w=Px 的位置”,可以使用可持久化线段树维护这个东西。

时间复杂度 O(qlog2m)

滚榜

给定一个长度为 n 的数组 a,求有多少 1n 的排列 p,满足存在一个 b=m 的不下降序列 b,使得对于任意 i,ji<j),都有:

  • apj+bpjapi+bpi+[pi<pj]
  • api+bpiapj+[pj<pi]

1n131m5000ai104

容易发现 b 的分配是贪心的,每次给出最小的 b,只要 bm 就是合法的方案。

一个显然的结论是“当前选手想当 rank 1 只要比上一名选手高即可”,这是因为上一名选手是当前的 rank 1。

于是可得(忽略编号问题,这个显然是容易处理的):

  • 如果 aiai1,则 bi=bi1
  • 如果 ai<ai1,则 bi=bi1+aiai1

综合一下上面两个式子其实就是 bi=bi1+max(0,aiai1)

进而通过考虑贡献可以知道 b=max(0,aiai1)(ni+1)(每个贡献都是一个后缀)。

于是考虑状压 DP,用 f(S,i,j) 表示,当前使用过的集合是 S,最后一个选的是 i,以及当前对 b 的贡献是 j。转移的时候枚举接下来选哪一个人,计算一下贡献即可。

时间复杂度 O(2nn2m),轻微卡常。

posted @   syksykCCC  阅读(1375)  评论(5编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探
点击右上角即可分享
微信分享提示