JOISC 2021 简要题解

「JOISC 2021 Day1」饮食区

  • 维护 \(n\) 个队列,支持 \(m\) 次操作:
    • \([l,r]\) 号队列的尾端均加入 \(k\) 个颜色 \(c\) 的球。
    • \([l,r]\) 号队列的前 \(k\) 个球 pop,如果不足 \(k\) 个则清空队列。
    • 输出第 \(a\) 号队列第 \(b\) 个球的颜色,如果不足 \(b\) 个球输出 \(0\)
  • \(n,m\leq 2.5\times 10^5,k\leq 10^9,b\leq 10^{15}\)

一开始 naive 地以为直接删除了就给 \(b\) 记录一个偏移量 \(k\),然后整体二分即可。

唯一不足的地方在于,如果队列清空,就不能加上对应删除的 \(k\),而是只加上 \(\text{size}\)

正着求这个 \(\Delta\) 不好做,考虑维护每个队列当前的球数 \(x\),以及总共进入过队列的球数 \(y\),那么 \(\Delta = y-x\)

维护当前队列球数,相当于每次 \(\forall i\in[l,r],x_i\gets \max(x_i+v,0)\)

这玩意挺经典的,可以直接用矩阵拟合,也不用真的维护矩阵,而是手玩两下得到合并式。

\((a,b)\) 表示 \(x_i\gets \max(x_i+a,b)\)\((c,d)\) 同理,那么 \((a,b)\cup (c,d)=(a+c,\max(b+c,d))\)

「JOISC 2021 Day2」道路建设

  • 输出 \(n\) 个点中两两前 \(k\) 小哈密顿距离的值。
  • \(n,k\leq 2.5\times 10^5\)

肯定是一手二分答案。

然后我的思考是硬上三维偏序,实际上判定的时候,相当于 \(n\) 个矩形数点,离线下来即可。

更巧妙的可以转切比雪夫,用一个 set 维护 \(y\) 坐标暴力跳就行,找到一个花费 \(O(\log n)\),找到 \(>k\) 个直接 return false 即可。

「JOISC 2021 Day3」保镖

  • \(n\) 个 vip 在直线上行走,表现为从 \(t_i\) 时刻开始从 \(a_i\) 走到 \(b_i\),每个单位时间走一个单位长度。
  • 你作为保镖也在行走,如果你某个时刻与某个 vip 位置重合,那么你可以开始保护他,每保护 vip \(i\) 一个单位时间就会获得 \(c_i\) 的收益。
  • \(q\) 次询问,每次给出你可能的开始行走的位置和时间,求你最终能获得的最大收益。
  • 即使你某个时刻与多个保镖重合,你也只能保护一个。同时,你可以不完整的保护一个 vip,甚至可以不保护他整数单位时间。
  • 但是数据保证 \(c_i\) 为偶数,可以证明这种条件下答案也一定为整数。
  • \(n\leq 2800,q\leq 3\times 10^6,t,a,b,c\leq 10^9\)

行走是一维的,但是有时间轴,所以实际上是二维问题,一定记得将问题转化到坐标系上。

先不急,先考虑一个性质:保镖不会停留。

因为停留无非是为了等待一个 vip,但是一直往他的方向走,并且在相遇的那条边先走 \(\frac{1}{2}\) 再折返是不劣的,所以不用停留。

将问题表达到坐标轴上,那么每个 vip 为线段 \((t_i,a_i)\to (t_i+|a_i-b_i|,b_i)\),一定是平行于 \(y=\pm x\) 的。

不如旋转 \(45^{\circ}\),进行 \((x,y)\to (x+y,x-y)\) 的变换(虽然这实际上是:逆时针旋转 \(45^{\circ}\) 并按 \(y=x\) 对称并伸长 \(\sqrt 2\) 倍,但无关紧要)。

发现转化为二维问题也乘了个 \(\sqrt 2\),所以直接令 \(c_i\gets \frac{c_i}{2}\) 就好了。

因为 vip 数很少,所以直接离散化能得到一个 \(2n\times 2n\) 的网格图,边有边权和长度,可以直接把图建出来。

问题转化为:给定网格图,你从某个位置出发,只能往右或往上走,每在一条边上走一个单位长度就能获得对应边权的收益,最大化总收益。

格点可以直接简单 DP,但是你可能是从非格点出发的。

显然最优决策一定是:先沿着一个方向走到某条格线,再沿另一个方向走到最近的格点,之后直接利用格点的 DP 值作为答案。

不同初始方向可以分开求解,以先往右为例。

此时可以每行分开处理,倒序维护,相当于每次插入一次函数 \(y=k_ix + b_i\),每次询问给定 \(x\)\(\max y\)

可以直接用李超树,因为是插入直线,所以复杂度 \(O((n^2+q)\log n)\)

实际上能做的更好,转化一下能变成 \(b_i=(-k_i)x+y\),最大化截距 \(y\) 所以维护上凸壳。

同时观察到 \(b_i\) 的单调不降性,所以如果 \(k_i\) 不是递增的,那么一定不优,所以可以理解为 \(-k_i\) 是递减的,即插入点的横坐标递减。

直接维护单调栈,每次二分即可,复杂度 \(O(n^2+q\log n)\)

「JOISC 2021 Day3」聚会 2

  • 对于一个树上有 \(k\) 个点的点集,定义 \(S\) 为它们的决策集合,\(s\) 包含所有到这 \(k\) 个点距离和最小的点。
  • 现在 \(k\) 个点可以钦定,求 \(\forall k\in[1,n],|S|_{\max}\)
  • \(n\leq 2\times 10^5\)

不难发现 \(k\) 为奇数的时候,一定有 \(|S|_{\max}=1\),且这个点是 \(k\) 个点中的一个。

更进一步的,发现 \(k\) 为偶数时,答案就是最长的路径长度,使得路径两端点的子树大小均 \(\geq k/2\)

统计路径长度使用点分治,每次开桶维护每个子树,桶的大小为 \(\text{siz}_v\),所以可以直接合并,每个桶时刻要取后缀 \(\max\)

「JOISC 2021 Day4」活动参观 2

  • 给定 \(n\) 个活动,每个活动需要占用一段连续的时间 \([l_i,r_i]\)
  • 求字典序最小的长度为 \(k\) 的序列,使得序列中的活动时间无交。
  • \(n\leq 10^5,l_i<r_i\leq 10^9\)

一开始是想着线段树优化建图的,但是应当是假了。

考虑对着字典序贪心,如果加入这一段后,最终还能得到 \(k\) 段就直接加入。

只需要维护函数 calc(l, r) 表示对于子区间 \([l,r]\) 最多能选几个线段,那么就可以直接贪心。

然后这种选不交区间的模型也是经典的倍增优化贪心了。

「JOISC 2021 Day4」最差记者 4

  • 每个人三个参数 \((a,h,c)\),分别表示 \(h_i\geq h_{a_i}\),以及修改 \(h_i\) 需要 \(c_i\) 的代价。
  • 需要满足所有不等关系,求最小修改代价。
  • \(n\leq 2\times 10^5,h_i,c_i\leq 10^9\)

遇到很多次这种线段树合并优化 树上带前后缀 \(\max/\min\) 之类的转移式了。

一定记住重要思想是,因为是前后缀,只要能取到答案就行,具体点值可以含糊。

显然连出来一棵内向基环树森林,把环拆了,先对子树求解。

一般都先想暴力一点,设 \(f(u,x)\) 表示点 \(u\) 的值取 \(x\) 的最小代价,则:

\[f(u,x)=[x\neq h_u] c_y+\sum_{v\in\text{subtree}(u)} \min_{y\geq x} f(v,y) \]

树上的点值,会取到的只有出现过的点值,所以是 \(O(n^2)\) 的。

对于环上的点,它们的值肯定全都相等,要么等于环上某个点的值,要么 \(=1\),枚举统计即可,这一部分是 \(O(n)\) 的。

这种转移方程一看就是能线段树合并优化的,但是最前面一项 \([x\neq h_u] c_y\) 意味着每次都要进行前后缀加。

线段树合并每次只能修改已有节点或插入有限个节点,这样强行打区间加 tag 肯定是会出问题的。

实际上,简单转化一下,\(f(u,x)\) 表示能保留的最大的代价和,那么:

\[f(u,x)=[x= h_u] c_y+\sum_{v\in\text{subtree}(u)} \max_{y\geq x} f(v,y) \]

维护子树 \(\max\),然后右子树对左子树有贡献,同时如果一个节点为空,那就对另一个直接区间加。

显然为了保证复杂度不能继续合并下去,而区间加看似没有对每个位置加上自己的后缀 \(\max\),因为左右均为空时,区间加没贡献上去。

实际无关痛痒,因为每次还是能取到后缀 \(\max\)。也因此,查询 \(f(u,x)\) 的时候要查询整个 \([x,V]\) 后缀。

补集转化的思想还是挺重要的!

posted @ 2022-12-01 17:30  LPF'sBlog  阅读(441)  评论(1编辑  收藏  举报