梦熊 NOI2025

2025.7.4 第一场 Day1

  • T1

    交互题。(第一次考场几乎做出一道交互题??)

    我也不知道我是怎么做出来的。我感觉就是把一些找到的性质拼在一起就做出来了。

    注意一个交互题常见技巧:我们往往可以通过排除法不检索最后一个元素

  • T2

    其实这个题是可做题。可惜我考场脑抽去开 T3 了。

    最核心的一步优化:对于最优化问题,考虑对象的贡献在什么时候一定不优,从而简化情况。

    具体的我写在注释里面。

    
    /*
    lxl
    
    即最大子集,使得 ai < bj 对于任何 i != j 成立
    
    如果有 ai < bi:
    考虑枚举 max ai,然后数前缀中 > max ai 的 bj 个数。
    每次插入新的数,修改操作为
    1.  对 ai < aj < bi,++
    2.  其本身加上 aj < ai < bj 的贡献。
    
    如果存在位置有 ai > bi,如何解决?
    等价于在集合中,有 ai < min_{j!=i} bj
    依旧枚举 max ai,然后限制为:
    1.  max ai < bj
    2.  max aj < bi
    于是找到前缀代表 min(ai, bi)
    然后再询问有多少 bj > ai
    这对吗?对的,但是是二维数点,双 log。
    
    aj < min(ai, bi) <= ai < bj
    (这里可以看出如果两个 ai < bi 一定不能同时待在集合里。)
    所以只用记录 ai < bi,然后记得更新对 bi < ai 的贡献即可。
    aj < bi < ai < bj
    计算覆盖整个 [bi, ai] 区间的区间数量。
    
    这里有一个不太算我独立想出来的优化方法:
    考虑到一个 [bi, ai] 的贡献只是 +1
    所以如果存在与 [bi, ai] 相交的区间的话,其就一定不是最优了。
    (思想:对于最优化问题,考虑对象的贡献在什么时候一定不优,从而简化情况)
    所以检查一下有没有相交区间就好了。
    
    具体实现:
    1.  线段树,记录 ai < bi 的区间的贡献。
    2.  树状数组,记录 ai < bi 区间端点,用于在插入 bi < ai 时检查是否有相交
    3.  ?某种数据结构,可以查询是否有 bi < ai 类区间相交,要支持删除。
    看来用 set 会是比较好的选择。
    */
    
  • T3

    没有学过闵可夫斯基和优化 DP 导致的。具体见:

    这个东西不好实现。需要用可并堆 / dsu on tree + 平衡树,而且这道题涉及到 \(h_{i-j} = f_i * g_j\) 这种玩意儿,还需要开多个堆来维护。


2025.7.5 第一场 Day2

  • T1

    对 Trick 不熟练导致差点没想出来。

    1. 建模为图。发现结构可以化简为树。

    2. Trie 上搜索处理异或最值问题。在看到某一个数 \(x\) 与一堆数之间的异或限制时就可以考虑。类似的题目:P10218 [省选联考 2024] 魔法手杖

  • T2

    我真觉的这个题很板没什么好说的。需要注意的是在 linux 系统下,输出字符时,如果出现了乱码,说明你可能输出了空字符。

  • T3

    十分神秘。

    第一步感觉就不是我这种人能想到的:考虑简化为一维的情况。发现在 \((x-1, y)\) 处操作可以将 \((x, y)\) 转化为 \((x-1, y), (x-1, y-1)\),即向左平移为一条竖线。那么我们可以将所有的点都平移到同一条竖线上去。

    考虑一个点在平移到这条竖线后呈现的图案。你可以发现平移的过程类似于杨辉三角,每个点是 0/1 实际等价为 \(\dbinom{\Delta x}{\Delta y} \bmod 2\)。根据 Lucas 定理,我们可以得知上式为 \(1\) 当且仅当 \(\Delta y\) 的二进制表示被包含于 \(\Delta x\)

    由于一个点平移结果的两端一定是 \(1\),所以如果我们找到了竖线上两端的 \(1\),就能确定答案。怎么求呢?

    先考虑 \(Y = 0\) 的部分分做法。一个很聪明的做法是:如果我们最终取的竖线为 \(x = 1-2^k\),那么该竖线上呈现的图象一定是连续的 \(1\)。于是二分出左右两端的 \(1\) 即可。然而正解与这个没有什么关系,因为在一般情况下,二分是不方便做“是否有点在左/右侧”的判定的。

    考虑化简问题。实际我们只要找到任意一个竖线上的点,就一定能找到左右两端的点——因为上面提到的 \(\Delta y\) 的二进制表示被包含于 \(\Delta x\) 的性质,我们可以在 \(O(\log V)\) 的时间复杂度内通过枚举 \(2\) 的次幂拼出左右两端。(这个东西还有一个理解方式是杨辉三角的分形结构,你可以打个组合数模 2 的表出来看看。)

posted @ 2025-07-04 21:18  David_Mercury  阅读(43)  评论(0)    收藏  举报