PKUSC2024 题解


By DaiRuiChen007




D1T1. 回文路径

Problem Link

给定 2×n 网格,每个格子上有一个字符,考虑一条只能向下和向右走的路径,如果路径上每个字符连成的字符串是回文串,称这条路径是好的,求最长好路径。

数据范围:n105

枚举回文中心,不妨设其在第一行,那么二分出在只在第一行能走到的最长距离,然后在右端点向下走一步,再二分在第二行能移动到最长距离。

可以用哈希快速判断路径是否回文。

时间复杂度 O(n)

Submission Link




D1T2. 正方形计数

Problem Link

给定凸 n 边形 (x1,y1)(xn,yn),求有多少正方形(可以是斜正方形)在该多边形内。

数据范围:n8,xi,yi2000

考虑枚举正方形的一条边向量 (Δx,Δy),然后对起点坐标有若干限制,可以写成半平面交的形式。

相当于数某个多边形内部整点数,可以拆成对 O(n) 条线段下方的区域内数点个数,类欧几里得算法解决。

时间复杂度 O(nV2logV)

暴力能过,没写正解。

Submission Link




D1T3. 独立

Problem Link

给定 n 个点的树,每个点点权在 [1,m] 中随机,求所有方案下树上最大权独立集的和。

数据范围:n2000,m108

考虑求最大权独立集的 dp 算法:dpu,0/1 表示 u 没选 / 选时的最大独立集,转移如下:

dpu,0=vson(u)max(dpv,0,dpv,1)dpu,1=wu+vson(u)dpv,0

其中 w 表示权值,记 au=max(dpu,0,dpu,1)dpu,0,带入可得 au=max(0,wuvson(u)gv)

并且整棵树的最大权独立集就等于 au,因此可以根据 au 设计 dp 套 dp 算法。

fu,i 表示 au=i 的方案数,那么转移时先求 gfv 的卷积,然后 fu,max(ji,0)gi,其中 j[1,m] 表示 wu

答案就是 uimnsiz(u)×i×fu,i

可以写出如下 48 分暴力:Submission Link

注意到我们要对 fu,0 特殊处理,用 msiz(u)i>0fu,i 更新,此时 fu,i=j=1migj

可以用归纳法证明,对于每个 ufu,1fu,m 是某个 O(n) 次多项式在 x=1m 处的点值。

不妨设 k=n+O(1) 表示多项式最高次数,我们只要维护 fu,1fu,k 即可插值出整个 fu

考虑如何转移,首先我们发现 fu,mkfu,m 是容易求的,只要求 g0gk 即可,这个可以用 NTT 快速求出。

然后我们要考虑 fu,mkfu,m 通过拉格朗日插值求出 fu,1fu,k,这个也可以求出式子后用 NTT 加速。

最后我们要求 i=1mfu,i 来更新 fu,0,求 i=1mi×fu,i 来更新答案,显然这两个值也是关于 mO(n) 次多项式,通过 fu,1fu,k 来插值求答案即可。

时间复杂度 O(n2logn)

Submission Link




D2T1. 分流器

Problem Link

在一张 n+1 个点的图上,1n 出度都为 2,在这个图上做一个类似 Shannon 投球游戏的过程,求最小周期。

数据范围:n50000

考虑维护 1i 的最小周期,并且求出此时每个点被经过的次数 fi

可以据此计算出 fi+1=i+1out(u)fu2,如果 2fi+1 那么最小周期要翻倍,每个 fi×2

一个较好的实现是令 f1=2n,答案就是 mini=1nlowbit(fi),压位高精度维护。

时间复杂度 O(n2ω)

Submission Link




D2T2. 排队

Problem Link

给定 n 个区间 [li,ri],定义 fi(x)=x+[lixri]q 次询问 L,R,求 fR(fR1(fL(0)))

数据范围:n,q106

考虑扫描线,枚举 R 对每个 L 维护答案 xL,显然 xL 单调不增,证明如下:

考虑 xi,xi+1,若某个时刻 xi=xi+1,此后所有时刻都有 xi=xi+1,由于初始 R=i+1xixi+1,因此 xi+1 不可能反超 xi

线段树维护所有 xi,二分出 xL[li,ri]L 区间,区间加即可。

时间复杂度 O((n+q)logn)

Submission Link




D2T3. 最短路径

Problem Link

给定纯随机的 n 个点 m 条边的带权有向图,q 次随机询问某对点 ST 的最短路。

数据范围:n2×105,m3×106,q104

很显然只能用一些魔改的最短路算法解决。

单向 Dijkstra 显然不太靠谱,不妨考虑双向 Dijkstra,即从起点和终点分别开始,在原图和反图上增广最短路。

Su 最短路 fuuT 最短路 gu

两棵最短路树考虑第一次相遇的时刻,设相遇在 x 上:

那么考虑答案的形态,首先全部经过最短路树的路径 fx+gx 先考虑贡献。

对于一个不全在最短路树的路径,如果这条路径经过一个最短路树外的节点 y,那么 fyfx,gygx,这条路径肯定不优。

因此不在最短路树内的部分只可能是一条边。

然后我们分析一下最短路树的期望大小,注意到 Dijkstra 的过程中每次弹出堆顶相当于取出当前权值最小的一条边,而这条边的权值和这条边的终点没有关系,因此每次 Dijkstra 拓展到的点可以被认为是 [1,n] 内均匀随机的。

所以我们每次拓展较小的一棵增广路树,根据生日悖论,期望 O(n) 次增广就能相遇。

但是这个复杂度并不对,因为每个点度数可能很大,增广到这个点的时候就会向堆中加入大量边。

因此我们考虑 k 短路的常用技巧,用左兄弟右儿子表示法维护这个图。

即堆中存储每一条边,增广的时候只将新节点的第一条出边入队,并且把当前边同一起点的后继边也入队。

那么这样每次增广只会加入 O(1) 条边,入队次数和增广次数成线性。

然后考虑如何算答案,即怎样枚举所有可能的增广路树外的一条边。

对于某条边 (u,v,w),其贡献为 fu+gv+w,对答案有影响显然要求 fu+gv+w<fx+gx

因此 w<(fxfu)+(gxgv)2max(fxfu,gxgv),我们在取到较大的一边考虑。

不妨设 fxfu 较大,那么我们只关心 u 的出边中 <2(fxfu) 的边,同理只关心 v 的反图出边中 <2(gxgv) 的边。

对每个点出边排序后即可做到只处理合法边。

考虑分析其边数,如果 w<fxfu,那么这条边在 Dijkstra 过程中一定被访问过,这样的边总数是期望 O(n) 的。

同理,我们可以猜测 w<2(fxfu) 的边也大约是 O(n) 量级,实际能分析出是 O(nlogn) 级别的。

时间复杂度 O(mlogm+qnlogn)

Submission Link

posted @   DaiRuiChen007  阅读(433)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示