因为今天考到莫队裸题了嘤嘤嘤...而我这样的蒟蒻肯定不会这样的高端算法啊QAQ。于是暴力水了40分qwq。

正如上文所说,我实在太菜了,于是学习莫队也只是学习了最简单的不带修普通莫队,如果我能苟到省选那就再继续学啦。

掏心推荐:深度好文,浅谈根号算法--分块 By new2zy


一、莫队的思想及处理的问题

红太阳金涛说的吼啊:莫队本质上就是一种优化的暴力

所以莫队到底能适用什么样的问题呢?基本上所有的离线区间查询问题(暂时不带修)都能用莫队算法苟过233...所以莫队算法还真是强啊%%。

离线区间查询?意思就是在说,我们先把所有需要进行区间查询的信息保存下来,然后根据一定的方法规则对这些区间查询信息进行排序。(这里我们一会再说qwq)

排序之后,我们就可以用两个指针$posl$和$posr$(可能有些像cf上的two pointer?不太确定qwq),不断调整他们的位置直到与查询区间精确重合并维护$[posl,posr]$区间内的信息,来处理询问。

而莫队算法也是需要把序列分成很多块的(分块算法的好基友),一般是分成$sqrt(n)$块,当然也有其他玄学分块方式。

而莫队的时间复杂度一般是$O(n*sqrt(n))$的,具体分析过程我就光速逃了qwq。(不会qwq)

另外,刚才我们留了个锅,就是关于将询问排序的方法:

  • 一般的排序是这样的:先按左端点所在块排,再按右端点位置排。但是这个排序有时比较弱,卡不过毒瘤们的精心构造。
  • 于是产生了更加优秀的一种排序:按奇偶块排序。这也是比较通用的。如果区间左端点所在块不同,那么就直接按左端点从小到大排;如果相同,鸡块奇块按右端点从小到大排,偶块按右端点从大到小排。
bool cmp(query a,query b)
{
return (a.l/block)^(b.l/block) ? a.l<b.l : (((a.l/block)&) ? a.r<b.r : a.r>b.r);
}

至于证明...我太菜了放过我吧


二、丢几道例题跑

其实..莫队的核心代码除排序的cmp外只有四行...

        int l=ask[i].l,r=ask[i].r;
while(posl<l) remove(posl++); //当前区间左端点在查询区间的左边 想要向右移 但是因为当前的posl不在查询区间中所以把它对答案的贡献去除。
while(posr>r) remove(posr--); //其他同理233
while(posl>l) add(--posl);
while(posr<r) add(++posr);
ans[ask[i].id]=noww;

什么这不是六行嘛

例题1 小B的询问

莫队裸题。左右指针移动实际上就是数字的增减,我们改变了桶的大小(计数数组大小后),考虑如果一个数字p减小,那么它对答案的贡献就会少。少了多少呢?考虑完全平方公式。设$x=cnt[p]$。

$(x+1)^2$------->>>>>>$x^2$

$x^2+2*x+1$------->>>>>>$x^2$

显然少了$2*x+1$,那么增加同理。之后就是套裸的莫队了。

#include<cstdio>
#include<algorithm>
#include<cmath> using namespace std; int n,m,k,block,posl=,posr,noww;
int seq[],ans[],sum[];
struct query{
int l,r,id,in;
}ask[]; bool cmp(query a,query b)
{
return (a.l/block)^(b.l/block) ? a.l<b.l : (((a.l/block)&) ? a.r<b.r : a.r>b.r);
} void remove(int x)
{
sum[seq[x]]--;
noww-=*sum[seq[x]]+;
} void add(int x)
{
sum[seq[x]]++;
noww+=*sum[seq[x]]-;
} int main()
{
scanf("%d%d%d",&n,&m,&k);
block=sqrt(n);
for(int i=;i<=n;i++) scanf("%d",&seq[i]);
for(int i=;i<=m;i++)
{
scanf("%d%d",&ask[i].l,&ask[i].r);
ask[i].id=i;
ask[i].in=ask[i].l/block;
}
sort(ask+,ask++m,cmp);
for(int i=;i<=m;i++)
{
int l=ask[i].l,r=ask[i].r;
while(posl<l) remove(posl++);
while(posr>r) remove(posr--);
while(posl>l) add(--posl);
while(posr<r) add(++posr);
ans[ask[i].id]=noww;
}
for(int i=;i<=m;i++) printf("%d\n",ans[i]);
return ;
}

例题2

也是一道裸的不带修莫队。因为每个数范围在1e9内,所以先离散化一下,然后上裸的莫队。但是正睿神机(?)竟然卡unique......嘤。

#include<cstdio>
#include<algorithm>
#include<cmath> using namespace std; int n,Q,block,m,posl=,posr,noww;
int seq[],b[],tong[],ans[];
struct query{
int l,r,id,in;
}ask[]; void re(int &x)
{
x=;
char ch=getchar();
bool flag=false;
while(ch<''||ch>'') flag|=(ch=='-'),ch=getchar();
while(ch>=''&&ch<='') x=(x<<)+(x<<)+(ch^),ch=getchar();
x=flag ? -x : x;
} bool cmp(query a,query b)
{
// return (a.l/block)^(b.l/block) ? a.l<b.l : (((a.l/block)&1) ? a.r<b.r : a.r>b.r);
return a.in==b.in?(a.in&)?a.r<b.r:a.r>b.r:a.in<b.in;
} void remove(int x)
{
tong[seq[x]]--;
if(tong[seq[x]]==) noww++;
if(tong[seq[x]]==) noww--;
} void add(int x)
{
tong[seq[x]]++;
if(tong[seq[x]]==) noww++;
if(tong[seq[x]]==) noww--;
} int main()
{
re(n);re(Q);
for(int i=;i<=n;i++) re(seq[i]),b[i]=seq[i];
sort(b+,b++n);
// m=unique(b+1,b+1+n)-(b+1);
for(int i=;i<=m;i++) seq[i]=lower_bound(b+,b++m,seq[i])-b;
block=sqrt(n);
for(int i=;i<=Q;i++)
{
re(ask[i].l);re(ask[i].r);
ask[i].id=i;ask[i].in=ask[i].l/block;
}
sort(ask+,ask++Q,cmp);
for(int i=;i<=Q;i++)
{
int l=ask[i].l,r=ask[i].r;
while(posl<l) remove(posl++);
while(posr>r) remove(posr--);
while(posl>l) add(--posl);
while(posr<r) add(++posr);
ans[ask[i].id]=noww;
}
for(int i=;i<=Q;i++) printf("%d\n",ans[i]);
return ;
}

更强的莫队算法,以后再见啦:)(如果我联赛后还能继续苟233)

莫队初探(不带修/例题极少)By cellur925的更多相关文章

  1. 【树上莫队】【带修莫队】【权值分块】bzoj4129 Haruna’s Breakfast

    #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using ...

  2. 【树上莫队】【带修莫队】bzoj3052 [wc2013]糖果公园

    #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using ...

  3. 【树上莫队】【带修莫队】【权值分块】bzoj1146 [CTSC2008]网络管理Network

    #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using ...

  4. 「洛谷1903」「BZOJ2120」「国家集训队」数颜色【带修莫队,树套树】

    题目链接 [BZOJ传送门] [洛谷传送门] 题目大意 单点修改,区间查询有多少种数字. 解法1--树套树 可以直接暴力树套树,我比较懒,不想写. 稍微口胡一下,可以直接来一个树状数组套主席树,也就是 ...

  5. 【BZOJ2120】数颜色(带修莫队)

    点此看题面 大致题意:告诉你\(n\)只蜡笔的颜色,有两种操作:第一种操作将第\(x\)只蜡笔颜色改成\(y\),第二种操作询问区间\([l,r]\)内有多少种颜色的蜡笔. 考虑普通莫队 这题目第一眼 ...

  6. P5168 xtq玩魔塔 [克鲁斯卡尔重构树+带修莫队]

    P5168 xtq玩魔塔 又是码农题- 利用克鲁斯卡尔重构树的性质 我们就可以得出 \(dep\) 值小的,肯定比 \(dep\) 大的值要优. 于是第二问就可以直接 LCA 求出来了- 至于第三问, ...

  7. 【洛谷】1494:[国家集训队]小Z的袜子【莫队】

    P1494 [国家集训队]小Z的袜子 题目描述 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… ...

  8. BZOJ 4129 Haruna’s Breakfast (分块 + 带修莫队)

    4129: Haruna’s Breakfast Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 835  Solved: 409[Submit][St ...

  9. 【bzoj4129】Haruna’s Breakfast 带修改树上莫队+分块

    题目描述 给出一棵树,点有点权.支持两种操作:修改一个点的点权,查询链上mex. 输入 第一行包括两个整数n,m,代表树上的结点数(标号为1~n)和操作数.第二行包括n个整数a1...an,代表每个结 ...

随机推荐

  1. linux下DOS工具

    1.Hping3/Nping TCP/IP数据包生成工具,用于压力测试,安全审计 2.使用hping进行DOS攻击 命令:hping3 -c 10000 -d 120 -S -w 64 -p 80 - ...

  2. 翻译:A Tutorial on the Device Tree (Zynq) -- Part V

    A Tutorial on the Device Tree (Zynq) -- Part V Application-specific data 之前提过,设备树中是一些特殊信息,这样一个驱动可以管理 ...

  3. firefox浏览器和IE

    http://blog.csdn.net/pipisorry/article/details/40899701 firefox浏览器插件 [下载地址add-ons for firefox]皮皮blog ...

  4. eclipse通过maven建立java se工程配置log4j,打包成zip,将jar包和配置文件分开,并以bat和sh文件启动java程序

    一.新建maven的java工程 1.eclipse里file-new-other,选择maven Project 2.选中 Use default Workspace location,然后 nex ...

  5. socketIO原理图

  6. Deep Learning 33:读论文“Densely Connected Convolutional Networks”-------DenseNet 简单理解

    一.读前说明 1.论文"Densely Connected Convolutional Networks"是现在为止效果最好的CNN架构,比Resnet还好,有必要学习一下它为什么 ...

  7. 使用forever让node.js持久运行

    何为forever?forever可以看做是一个nodejs的守护进程,能够启动,停止,重启我们的app应用. npm install forever -g #安装 forever start app ...

  8. vfork函数的使用【学习笔记】

    #include "apue.h" ; int main(void) { int var; pid_t pid; ; printf("before vfork\r\n&q ...

  9. POJ2243 Knight Moves —— A*算法

    题目链接:http://poj.org/problem?id=2243 Knight Moves Time Limit: 1000MS   Memory Limit: 65536K Total Sub ...

  10. HDU1241 Oil Deposits —— DFS求连通块

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1241 Oil Deposits Time Limit: 2000/1000 MS (Java/Othe ...