2019-2020 ICPC Asia Hong Kong Regional Contest

A - Axis of Symmetry

一道非常有趣的题目。感觉官方题解不太详细啊……很多东西都没有点出来。

首先有一个结论:答案最多只有 \(4\):水平竖直及两条斜率分别为 \(\pm 1\) 的直线。具体可以算出横纵坐标的最大最小值得到。

不过官方题解的思路是富有启发性的:考虑如果矩形间全部不相邻,那么直接判所有的矩形边界线段即可。然而由于存在两个小矩形合并为大矩形的情况,直接操作会误判。然后我们需要进行一些操作:将相接的线段合并,以及删去两个矩形的公用边。

但我们可以不这么实现,因为细节不清不楚而且比较复杂。我们判线段,本质上在判线段上的点。能不能直接判点集的对称性呢?

对于干扰点,其可能的情况为:在(组合)矩形的边上,或被四个矩形包夹。这些点不能表现图案,但会使我们误判。观察得知,成为这种点有一个充要条件,就是作为矩形的角出现偶数次!

也就是说,我们筛去这些点,剩下的点就能反映图案的所有“拐角”,也就表现了图案。其实筛掉这些点,实际上和官方题解提到的方法本质相同。

最后判对称的话,这么做都可以了。复杂度 \(O(n\log n)\)

B - Binary Tree

噗 什么演王题

考虑到每次取走的子树大小必然为奇数。

所以判断 \(n\) 的奇偶性即可。

C - Constructing Ranches

首先考虑一列数 \(a_{1\sim n}\) 可以构成简单多边形的一个简洁的充要条件:\(2\cdot \max_i a_i <\sum_i a_i\)

然后大致的做法就比较清楚了,点分治统计合法路径数。

对于两条路径,其路径最大值分别为 \(x_1, x_2\),路径和分别为 \(y_1,y_2\)。那么简单推导,产生贡献的条件有:\(\begin{cases} x_2<x_1 \\ y_2 > 2x_1-y_1 \end{cases}\)(其中 \(x_2<x_1\) 可以确定最大值)。

很显然是一个二维偏序问题,使用容斥统计可以变成静态问题,扫描线树状数组可以解决。算上分治时间复杂度 \(O(n\log ^2 n)\)

一个细节就是,然后处理两条路径对接时分治中心的影响(单独说一下是因为没想清楚被卡了好久)。第一种方法是一开始不处理根,在后期统计时加上,但这样会影响最大值以及和两个指标,非常麻烦。而另一种方法是一开始就加上,这样后期就只要在和上减掉重复统计的中心即可,而最大值则不用管,会方便不少。

D - Defining Labels

找规律。对于一个 \(10-\textit{based}\) 编号 \(X_kX_{k-1}\cdots X_1X_0\),其对应的十进制真实值为 \(\sum_{i=0}^k (X_i +1) \times 10^i\)

类比到 \(k-\textit{based}\) 编号,只要做正常的进制转换,只是进入递归前将 \(X\) 减一,并加上 \(10-k\) 即可。

E - Erasing Numbers

又是神奇结论题。又是我不会的题。

首先发现 \(n\le 5000\),大概推测解法是对每个数都做一次 \(O(n)\) 的判断。那么对于每个数 \(x\) 做判断时,可以发现我们在考虑其他数时,可以只考虑其与当前数 \(x\) 的大小关系。于是小于的记为 \(0\),大于为 \(1\)

然后有一个结论:如果序列中 \(0\) 的数量和 \(1\) 相等,那么一定可以消到只剩下 \(x\)。可以发现,如果两者分别都在 \(x\) 两侧的各一侧,那么一定可以操作 0x11x0 直到剩下 \(x\)。如果是混杂的,那一定可以找到一个位置 \(0,1\) 相邻,然后使两者的数目各减去一。

当然不可能都是相等的,那么考虑将多出来的那个消去一些。注意到如果要消掉多余的 \(0\),那么只有 000 的情况是靠谱的。如果没有连着的,我们可以消去中间将其隔开的 01 达到目的。

于是有了这样的算法:扫过去,每当出现一个子段 \(0\)\(1\) 多三个,就可以直接减掉两个 \(0\)\(x\) 两侧各执行一次即可,直到数量相等则判断成功。

复杂度 \(O(n^2)\)​,感觉不是那么简单的题,为啥过了这么多啊。

G - Game Design

简单构造。首先根比较有用我们使其点权为 \(10^9\),让其对解数无影响。

考虑这个 \(K\) 实际必然是若干个数乘起来的结果,于是考虑在根上挂上若干条链,每条长度(点数)为 \(l\) 的链,我们令链上的点权为 \(1\),那么就是 \(l\) 种方案。

于是不难想到质因数分解:\(K=\prod_i^k p_i^{c_i}\)​。那么乘上一个 \(p\),就在根上挂一条 \(p\) 个点的链。

注意到我们有点数限制,而质因数分解就是为了把乘法变成加法使得点数为 \(\sum_i^k c_ip_i\)​ 规模。但如果 \(K\) 中存在一个巨大无比的质因子——或者说就是大质数(如 \(998244353\)),那点数还是太多。

考虑微操一下:我们尝试将 \(K\)​ 减一。可以发现这样其分解会有很大的变化,常数轮之后就没有过大的质因子了。得到处理过的 \(K' = K- t\)​ 后,对应的,在根下建 \(t\)​ 一个新点,那几条链连在这个新点而不是根上,新点的权值为链的数目。注意这时这些链由 \(K'\)​ 导出。很显然这时点数还是 \(O(\log K)\sim O(\log ^2 K)\) 左右,可以通过。

H - Hold the Line

单点加入(从无到有),区间查询前驱后继。在线的话,一看就是要维护动态的二维信息,那么一个线段树套 set 的大常数 \(\log ^2\) 做法是显然的。然而 \(n\le 5\cdot 10^5\) 这么大的数据肯定过不了,但由于这动态的二维信息摆在哪里,正解应该是离线小常数的 \(O(n\log ^2 n)\)

扫描线。我们固定右端点 \(R\),这时 \(\le R\) 的插入操作就已更新。考虑维护用一个以权值为下标的线段树,我们要求前驱或后继,可以直接在线段树上二分求解。每个线段树结点保存的是二维点集 \((t,p)\):插入时间 \(t\) 以及位置 \(p\)

于是,判断一个线段树结点是否包含可行点,只要查询每个点左上区域是否存在点即可。然后就是一个 trick:若存在 \(A,B\) 两点满足 \(A\)\(B\) 的左上方,那么 \(B\) 就完全没用了。删去所有这样的 \(B\),余下的点按 \(t\) 排序,\(p\) 也是单调的。这样就变成一维问题了!判断存在只要在单调点列上二分查找即可。

然而我们要支持动态插入,好像又要用 set 了!但注意到,我们有一维是位置,而推进扫描线使得加入的点在位置上就是天然单调的,仔细一想其实只要 vector 就行了。

最后复杂度是 \(O(n\log ^2n)\)

I - Incoming Asteroids

跟着这题学了个新 trick /se

考虑每个任务的 \(k\) 都很小,那么对这 \(k\) 个位置都设一个 \(\lfloor y/k \rfloor\) 的阈值。每当 \(k\) 个位置的其中一个达到了这个阈值就重构这个任务并重新放置。(要说这怎么想到的……只能说 \(k\) 个位置都地位相等,自然阈值都相等;而要保证所设的阈值不能出现“完成了却不知道”,最大的可行阈值就是 \(\lfloor y/k \rfloor\))。

复杂度不难证明,由于一次重构意味着减小 \(1/k\),那么复杂度就是 \(O(n\log n\log y)\)。其中 \(\log n\) 是维护需要的数据结构的时间。

J - Junior Mathematician

摆明了是数位 dp。复习一下。

考虑我们记搜时要记录那些信息到状态里面:位数,是否有上界(基础信息,这里似乎不需要判前导零),\(x\bmod m\)\(f(x)\bmod m\) 以及数位和。

但是这样维度有点多,冷静分析可以发现 \(x\bmod m,f(x)\bmod m\) 这两个我们可以用一个 \(f(x)-x \bmod m\)​ 代替。

然后在转移注意下细节和卡常就好啦。写了个小丑 map 被卡爆了

K - Key Project

我网络流水平菜到离谱了哇

这题的费用流还是很明显的。建模:对每栋楼建点,对于一个 algorithm engineer(\(A\))我们从原点 \(S\) 向其所在建筑连容量为 \(1\),花费为 \(c_i\) 的边;对于一个 software engineer(\(B\))我们从其所在建筑向汇点 \(T\) 连边。

传统的 EK 费用流算法,复杂度为 \(O(m\cdot m\log n)/O(m\cdot nm)\),无法通过。考虑到这个算法慢在寻找最短路,而显然这张图是有特殊性质的,考虑优化最短路的寻找过程。

首先观察得知,对于所有 \(S\to i\) 的边,我们只保留(之前没用过的)花费最小的那条。对于 \(i\to T\) 的边同理。而且和源汇点连接的边不需要退流(即不需要反边)。

所以我们主要考虑的只有中间那 \(n\)​ 个点。相邻点之间有两个方向的边(方向不同,边权也不同还可能为负)。

接下来就能用线性的扫描代替最短路了。不是一般性设最终选取的组合 \(A\)\(B\) 左侧,维护左侧到当前位置的最短距离即可。反过来做一次就能处理 \(A\)\(B\)​ 右侧了。找到后记得更新边上的花费。

很显然一次扫描 \(O(n)\)​,总复杂度 \(O(nm)\)​。有点像模拟费用流? 一开始还在想用费用流证凸性然后胡乱凸包

代码还没有写完 写完了,就你卡常数是吧

posted @ 2021-10-27 22:01  -Wallace-  阅读(417)  评论(0编辑  收藏  举报