JOISC 2023

JOISC 2023

D1T1 Two Currencies

树上主席树板子。

提交记录

D1T2 Festivals in JOI Kingdom 2

啥时候我才能做出这种题啊?一步步跟着题解还想了半天才会。

正确做法是按照右端点贪,考虑补集转化,看看题解那些红蓝区间的限制,按照每次直接插入一对红蓝区间来 dp 可以做到 \(O(n^3)\)。注意到蓝区间左端点的限制很稀碎,考虑从右往左做 dp。这样的话没有考虑右端点的限制,然后左端点部分可以直接算。剩下的部分画画图就很简单了。

真是完全不会这种。

提交记录

D1T3 Passport

首先每个时刻到达的点构成了一个区间,那么可以到达所有点等价于可以到达 \(1\) 号点和 \(n\) 号点。由此只用考虑点和点之间的路径。我们现在已知 \(1\) 号点和 \(n\) 号点到所有点的最短路,但是这两个最短路之间可能有边被重复计入贡献。考察 \(x \rightarrow 1\)\(x \rightarrow n\) 的关系。发现如果有一公共点 \(t\) 那么 \(t\) 前面的路径都是一样的。所以重复的部分一定是一个前缀。既然如此,那么我们初始令答案等于两条最短路的和,对于 \(x\) 我们考虑用所有出边来松弛,这又是一个最短路,这时候得到的答案就是正确的了。时间复杂度 \(O(n \log n)\)。连边的部分需要线段树优化。

提交记录

D2T1 Belt Conveyor

最直观的想法是每次操作一个点,然后看看它往哪个方向移动来确定一条边。注意到一个点最终的状态只会被相邻的点影响,我们按照模 3 来分类,这样的话一次就可以直接操作同一类点。每次操作一个点至少能确定一条边,故取三类点中还有相邻未知边的点数最大者,那么每次至少能确定 \(\lceil \frac{e}{3} \rceil\) 条边,这样就可以在 \(30\) 次操作内确定所有边。

提交记录

D2T2 Council

首先观察一下,发现票数变动至多为 \(2\)。固定 \(a_i\) 后发现只有当前票数为 \(\lfloor\frac{N}{2}\rfloor\) 的议案可能改变。不妨设可能改变的集合为 \(S\),这样如果选出副主席的集合为 \(T\),就有 \(|S \cap T|\) 这么多的议案是要减去的。考虑补集转化,变成求 \(\max_{j \not = i}|S \cap T|\) 这个东西可以一次高维后缀和再来一次高维前缀和,复杂度 \(O(m 2^m + nm)\)

提交记录

D2T3 Mizuyokan 2

考虑 dp 啊,很难。发现极小段段长为 \(1\),所以可以直接用分治之类的做这个 dp,然后就会 \(O(nq\log n)\) 了。但是这样很小丑,因为还能发现最长段段长是 \(O(\log V)\) 级别的,所以直接枚举从哪里转移来就能 \(O(nq \log V)\)。但是这个东西没办法优化。

考虑更好的做法,设 \(pre_i\) 表示 \(i\) 前第一个能转移到 \(i\) 的点,如果 \(pre_i\) 前面的都能转移到 \(i\) 那自然是很舒爽的。可惜不行。那我们先做个梦假装 \(pre_i\) 前面都能转移,这样怎么做呢?我们可以发现每次都会转移到最近的点,那么就是 \(i\) 向后面第一个 \(pre_j \ge i\)\(j\) 连边,然后跳跳跳。然后你惊奇地发现不需要 \(pre_i\) 前面都能转移也可以这么做。就得到了一个容易优化的做法。

为什么这样是对的呢?考虑 \(i\) 转移不到 \(j\),但是 \(k > i\) 可以转移到 \(j\),那就有 \(a_k < s(k,j) < s(i,j) \le a_i\)。至于前面的部分,假设 \(p\) 转移到 \(i\),也有 \(a_k < a_i < s(p,i) < s(p,k)\)。所以可以直接从 \(k\) 处转移。非常nice。

现在整理一下,我们的做法是对每个 \(i\) 求出 \(i\) 前第一个能转移到 \(i\) 的点 \(pre_i\),然后求出 \(i\) 后第一个满足 \(pre_j \ge i\) 的点 \(nxt_i\)。从左边的 \(O(\log V)\) 个点开始跳 \(nxt_i\) 链,跳到的点就是极小段,可以直接算答案。

这东西怎么维护呢?直接在线段树上跳就好啦,每次只会改长度为 \(O(\log V)\) 的区间的信息,然后修改时就找到对应结点再跑建树的代码就行啦。复杂度 \(O(q \log n \log V + n \log V)\)

提交记录

D3T1 Chorus

这题你们都咋写的啊?为啥我感觉我的斜率优化好复杂?

原本想要像上一题一样找一些好的性质,但是发现性质好像会把问题变得更加复杂,于是直接从暴力 dp 入手。设 \(f_{i, j}\) 表示考虑到第 \(i\)A 时已经选出了 \(j\) 个子序列,然后转移其实是比较简单的。设 \(pre_i\) 表示第 \(i\)A 前有多少个 B,那么代价 \(w(j, i) = \sum_{k=j+1}^i (pre_k - \min(j, pre_k))\)。盲猜一手这个东西是凸的,事实上可以通过四边形不等式来证明,那么可以考虑 wqs 二分,问题转化为给每次选子序列附加代价,求最小代价。这里可以直接利用决策单调性的那套理论做到比较优的复杂度。

上面的这个东西是可以斜率优化的。具体地,考虑处理出最后一个使得 \(pre_k \le j\) 的位置 \(pos_j\),那么就有 \(w(j, i) = s_i - s_{pos_j} - j (i - pos_j)\),这里的 \(pos_j\)\(j\) 取了 \(\max\)。但是很伤心,如果 \(pos_j > i\) 那么这个式子就错了。

继续观察性质,发现 \(pos\) 是单调的,所以满足 \(pos_j > i\)\(j\) 是一段后缀。同时这段中间可以通过这种形式互相转移,增量是二分的代价而已。所以我真正转移到 \(i\) 的只能是这个后缀的开头或末尾。这样子能转移到 \(i\)\(j\) 就是常数级别的了。复杂度 \(O(n \log V)\)

提交记录

D3T2 Cookies

\(m = 1\) 的问题太经典了。注意到一个贪心:每次只会选当前 \(a_i\) 最大的曲奇。所以选曲奇的策略很简单,那么我们只需要找一下盒子的可重集合法的充要条件即可。又有一个贪心:从大到小考虑每个盒子,然后能选就选。很遗憾假掉了,因为可能选了大盒子之后后面必须选小盒子更劣。考虑怎样更加简洁地描述限制,假设有 \(k\) 个盒子,一种曲奇至多选 \(\max(a_i, k)\) 个,所以所有盒子的容积之和不大于 \(\sum \max(a_i, k)\)。猜一下这个是充要条件然后就可以直接记录当前容积 dp 了,精细处理上下界,然后用 std::bitset 优化一下就能做到 \(O(\frac{n^2\log n}{w})\) 了。

提交记录

D3T3 Tourism

有很多做法。我想到了直接回滚 Mo's Algorithm 的最套路的做法。分治的做法是把询问挂在猫树上,然后转化成二维偏序。还有种 HH 的项链的做法,就是扫描线维护每个点最后被覆盖的时间,然后用一个树状数组维护答案,信息是后缀推平的形式,可以先树剖然后维护个 std::vector 搞定。

还是不会 LCT,伤心...

提交记录

posted @ 2023-10-13 07:23  DCH233  阅读(72)  评论(0编辑  收藏  举报