首页 > 其他分享 >莫队

莫队

时间:2024-08-03 19:50:31浏览次数:9  
标签:ccnt 询问 dfn 端点 区间 莫队

普通莫队

把询问离线下来,按左端点分块,同一个块内按右端点排序。

块长 \(b=\dfrac{n}{\sqrt m}\),注意特判 \(m=0\) 或让 \(b=0\) 的 sb 出题人,会 RE。

记录两个指针 \(l,r\),依次挪动到待查询区间。注意要先扩大再缩小,否则会出现正确性上的问题。

trick:奇偶排序

可以按照块序号的奇偶决定 \(r\) 的递增或递减。

感性理解:就是 \(r\) 在第一块从 \(1\) 跑到 \(n\),本来在第二块要回到前面再走一遍,结果第二块逆序排序,就在回来的路上解决了所有第二块的询问。

P2709 小B的询问

从 \(c\) 到 \(c+1\) 会产生 \(2\times c+1\) 的贡献。

从 \(c\) 到 \(c-1\) 会产生 \(2\times c-1\) 的负贡献。

记录一个桶和一个 \(sum\),硬算。

SP3267

区间数颜色个数,开个桶,摁做。

CF617E / P4462

询问区间内有多少个子区间的异或和为 \(k\)。

依然是数颜色,开个桶。

假如 \(a \oplus x=k\) 其中 \(a\) 已知,那 \(x=k \oplus a\),于是新加入一个 \(a\) 的贡献为 \(cnt_{k\oplus a}\)。

P3709

转换一下题意可得每次选无序上升子序列最优。

无序上升子序列:就是随便找一组上升的数,不考虑顺序。

也就是区间询问最少能被几个无序上升子序列覆盖。

考虑到每个数在一组无序上升子序列中只能被选到一次。

也就是求区间众数的大小。发现加很好做,但删除不太容易,于是就有了回滚莫队做法。

也可以记录一个桶的桶 \(ccnt\),就是记录出现次数的出现次数,外加一个指针记录当前最大的 \(ccnt\)。加入时让 \(ccnt_{k+1}+1,ccnt_{k}-1\) ,减掉时 \(ccnt_{k}-1,ccnt_{k-1}+1\)。

发现数字可能很大,但数字的种类不多,离散化即可。

P4867

数颜色种类,但是种类要求在一个值域范围内。

用值域分块即可。


带修莫队

直接上例题。

P1903

数区间颜色种类,带修。

用结构体存一下每个修改。

我们在原先排序的基础上,对于所有 右端点 在同一个块中的查询按 \(t\) 升序排序。

记录三个指针 \(l,r,t\),分别指向当前区间的左右端点、修改时间轴上的时间,每个查询先移动端点,再处理修改,在当前区间内的修改才需要统计贡献。

块长设到 \(O(n^{\frac{2}{3}})\)。

work 要传两个参数,询问和修改的编号,询问的编号仅用于查询是否与当前答案有关。

swap 的操作很巧妙,因为回溯的时候会把这个数交换回来,而其他修改与之无关。

CF940F

不会。


树上莫队

用于处理树上的区间查询。

而莫队只能在序列上用,建出这棵树的括号序并处理出 lca,按普通莫队去跑,分类讨论子树关系,然后特判 lca 的情况。

修改时注意不一定是加点或者删点,而要根据这个点的出现次数判断是加点还是删点。

规定第一次出现是 \(dfn\),第二次出现为 \(low\)。

SP10707 COT2 - Count on a tree II

树上的区间数颜色,树上莫队板子。

跑出括号序,有祖孙关系就存区间 \([dfn_x,dfn_y]\),没有祖孙关系就存 \([low_x,dfn_y]\),外加一个 \(lca\)(先要保证 \(dfn_x<dfn_y\))。

记录一个 bool 的 \(use[]\),访问过一回就删掉,否则就加上。


回滚莫队(只增加/只减少莫队)

步骤

  • 按普通莫队排序(不可以奇偶块优化)

  • 记录每个块的左右端点 \(L_i,R_i\)

  • 对于每个询问

    • 若左右端点在同一个块内:暴力

    • 否则

      • 之后会有一段询问 \(q[j].r>R_i\)
      • 将当前端点移动到 \(l=R_i+1,r=R_i\) 的位置
      • 先移动右端点到目标位置(询问的 \(r\) 单调递增)
      • 移动左端点到目标位置
      • 记录答案
      • 恢复左端点到 \(l=R_i+1\)

AT_joisc2014_c 歴史の研究

回滚莫队模板。

只有左右端点移动到指定位置的尾部时才能用 memset,因为只有根号次移动。

清空暴力的 cnt 数组和回滚的时候都不能 memset,这两个操作都会被卡到 \(O(n^2)\)。

标签:ccnt,询问,dfn,端点,区间,莫队
From: https://www.cnblogs.com/tai-chi/p/18340956

相关文章

  • Contest7506 - 莫队 分块
    ContestA至少重复三次的数字莫队板子。B小明的习题集洛谷原题P1494[国家集训队]小Z的袜子。C棋子的颜色洛谷原题P1903[国家集训队]数颜色/维护队列。带修莫队:普通莫队是二维问题,现在加上一维时间轴,做法基本上同普通莫队。对询问\((l,r,t)\)排序时,第一关键......
  • 【数据结构】【模板】莫队
    莫队使用场景离线算法;区间询问不断修改。能用\(O(1)\)的时间复杂度从\([l,r]\)到\([l+1,r]\)或者\([l,r-1]\)。原理原问题可以转化为为建立一个坐标轴,对于一个询问\((l,r)\),相当于点\((l,r)\),从一个询问\((a,b)\)到\((c,d)\),可以理解为点\((a,b)......
  • 莫队
    莫队假设\(n,m\)同阶,对于序列上的区间询问问题,如果得知\([l,r]\)的答案,可以在\(O(1)\)的时间推算出\([l-1,r],[l+1,r],[l,r-1],[l,r+1]\)的答案,那么我们就可以在\(O(n\sqrt{n})\)的时间求出所有询问的答案。普通莫队实现将所有的询问离线后以左......
  • 二次离线莫队
    更新答案不是\(O(1)\)?答案可差分?二离来啦。P4887【模板】莫队二次离线先考虑贡献:\(f(x,[l,r])\)表示\(x\)对区间\([l,r]\)。考虑莫队每次的移动:\(r\tor'\)。答案增加为:\[\sum_{i\in[r+1,r']}f(i,[l,i-1])=\sum_{i\in[r+1,r']}f(i,[1,i-1])-f(i,[1,l-1])\]发现前......
  • 莫队
    普通莫队DQUERY-D-query先想一下最朴素的暴力怎么写。显然可以用一个\(cnt\)数组记录每种元素的出现次数,然后如果这种元素是第一次出现,则增加答案,时间复杂度\(O(nq)\)。然后考虑如果如何用一个已经求出来答案的询问推出另外一个询问的答案。显然我们要增加一部分数和删掉......
  • 【离线】- 莫队
    前言莫队是由莫涛提出的一种离线算法,是分块与双指针的结合,一般可以在\(O(n\sqrtn)\)或者\(O(n\sqrtm)\)的复杂度解决一些种类问题。普通莫队SP3267DQUERY-D-query给你一个长度为\(n\)的数列\(A\),\(m\)次询问,每次询问区间\([l,r]\)内的不同数字的个数。如果......
  • 带修莫队模板
    取分块大小\(n^\frac{2}{3}\)最优。例题:数颜色#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;constintN=1e6+5;intcnt[N],a[N];structquery{intl,r,t,id;//加入时间戳};structmodfiy{intpos,val;};intmain(......
  • 莫队模板
    #include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;constintN=1e6+5;intcnt[N],a[N];structquery{intl,r,id;};intmain(){ios::sync_with_stdio(false);cin.tie(nullptr);intn;cin>>n;......
  • 从值域分块+莫队到二次离线莫队
    值域分块Q给定一个序列,实现单点修改\(O(1)\),以及区间查询\(O(\sqrtn)\)A考虑设\(block_i\)表示块\(i\)的和,那么修改便是\(O(1)\)全局查询时,整块调用\(block\),散块暴力即可\(O(\sqrtn)\)还有一些常见的例子,比如配合莫队代替主席树(区间mex)莫队二次离线普通莫队......
  • 算法课程笔记——普通莫队
    算法课程笔记——普通莫队......