[NOI Online 2021 提高组] 岛屿探险

  • 本文没有采用官方题解的\(cdq\)分治,而是采用了一种类似于\(seg\)分治的方法,因为代码暂时咕咕,不保证正确性,跪求大佬如果看出有错指教一下蒟蒻,欢迎\(hack\)
  • 题目链接:[NOI Online 2021 提高组] 岛屿探险
  • 题目简述:给1个序列,每个位置是一个二元组\((a,b)\),\(q\)次询问,每个询问形如l r c d\(\\\)
    询问有多少个\(i\)满足i >= l && i <= r && (a[i]^c) <= min(b[i],d)
  • \(n,q\leq 1e5,a_i,b_i,c,d \leq 2^{24} - 1\)
  • 时间限制\(1s\),空间限制\(256MB\)
  • solution:

  • 不妨先考虑一下若只有\(\leq d\)的限制怎么做
  • 这是一个经典问题,可以用可持久化\(Trie\)\(O(n \log n)\)内解决\((step.1)\)
  • 不妨再考虑一下若只有\(\leq b_i\)的限制怎么解决
  • 若沿用上面的思路很难做.我们反过来想,既然\(a_i,b_i\)都给定了,那么有哪些\(c\)满足a[i]^c <= b[i]是不是也确定了?
  • 这个也只需要建一颗可持久化\(Trie\),在上面打标记即可(建一棵完整的\(Trie\),沿\(a_i\)遍历下去,若某一位\(b_{bit}[i] == 1\),则将和\(a_i\)相同的一位所代表的子树打个标记)\((step.2)\)
  • 综合上述两个算法,我们可以在采用树套树算法,外层是\(step.1\)的树,内层套上\(step.2\)的树,可以做到时空\(O(n \log^2n)\)的复杂度
  • 但这个空间复杂度仍然不够优秀,我们考虑沿着\(trie\)树分治,我们考虑在\(step.1\)时,一个询问依赖\(d\)跑的时候,本质上是求在\(log\)棵子树中在不用考虑\(d\)的约束情况下满足条件的个数,因为\(step.1\)只有\(\leq d\)的约束,所以贡献就是\(size\)大小,那么在这里.贡献就是在这个子树中异或\(c \leq b_i\)\(a_i\)的个数,而这个可以利用\(step.2\)的方法来解决
  • 将每个询问拆成\(\log A\)个,放到子树中,每遍历到一个子树,对下标进行离散化,插入\(step.2\)的可持久化\(Trie\)中,即用即清空,因为每一层\(Trie\)大小最多是\(O(n\log A)\),所以总复杂度是时间\(O(n\log^2 A)\),空间\(O(n\log A)\)
posted @ 2021-03-27 17:32  y_dove  阅读(126)  评论(0编辑  收藏  举报