莫队算法

莫队在知乎回答了一波,推荐了一篇博客,但原网址挂了。最后凭借搜狗的网页快照,我终于一睹这篇博客的真容。

例题 (2010年国家集训队论文答辩)小K的袜子

对于询问\([L,R]\),设其中颜色为\(x,y,z...\)的袜子的个数为\(a,b,c...\)

那么答案即为\(\cfrac{\cfrac{a(a-1)}{2}+\cfrac{b(b-1)}{2}+\cfrac{c(c-1)}{2}+...}{\cfrac{(R-L+1)(R-L)}{2}}\)

化简得:\(\cfrac{a^2+b^2+c^2+...x^2-(a+b+c+d+.....)}{(R-L+1)(R-L)}\)

即:\(\cfrac{a^2+b^2+c^2+...x^2-(R-L+1)}{(R-L+1)(R-L)}\)

所以这道题目的关键是求一个区间内每种颜色数目的平方和。

对于一般区间维护类问题,一般用线段树,但是这题完全不知道线段树怎么做,搜索后得知是莫队算法。

莫队算法可以一个可高效解决绝大多数离线+无修改+区间查询问题的算法。这类问题具体是指:如果知道\([L,R]\)的答案时,可以在\(O(\mathrm{g}(n))\)的时间下得到\([L,R-1],\)\([L,R+1],\)\([L-1,R],\)\([L+1,R]\)的答案的话,就可以\(O(n\sqrt n · \mathrm{g}(n))\)的时间内求出所有查询。

对于莫队算法我感觉就是暴力。由于预先知道所有的询问,因此可以合理的组织计算每个询问的顺序以此来降低复杂度。

假设我们算完\([L,R]\)的答案后现在要算\([L',R']\)的答案。由于可以在\(O(1)\)的时间下得到\([L,R-1],\)\([L,R+1],\)\([L-1,R],\)\([L+1,R]\)的答案,所以计算\([L',R']\)的答案耗时\(|L-L'|+|R-R'|\)。如果把询问\([L,R]\)看做平面上的点\(a(L,R)\),询问\([L',R']\)看做点\(b(L',R')\)的话,那么时间开销就为两点的曼哈顿距离。

因此,如果将每个询问看做平面上的一个点,按一定顺序计算每个值,那开销就为曼哈顿距离的和。要计算到每个点,路径至少会形成一棵树。所以问题就变成了求二维平面的最小曼哈顿距离生成树。

这样只要顺着树边计算一次就OK了,可以证明时间复杂度为\(O(n\sqrt{n})\)(这个我不会证明),但是这种方法的编程复杂度稍微高了一点。

有一个比较优雅的替代品:先对序列分块,然后对于所有询问按照\(L\)所在块的大小排序,如果一样再按照\(R\)排序,最后再计算。为什么这样计算就可以降低复杂度呢?

一、\(i\)\(i+1\)在同一块内,\(r\)单调递增,所以\(r\)\(O(n)\)的。由于有\(\sqrt{n}\)块,所以这一部分时间复杂度是\(O(n\sqrt{n})\)
二、\(i\)\(i+1\)跨越一块,\(r\)最多变化\(n\),由于有\(\sqrt{n}\)块,所以这一部分时间复杂度是\(O(n\sqrt{n})\)
三、\(i\)\(i+1\)在同一块内时,变化不超过\(\sqrt{n}\),跨越一块也不会超过\(\sqrt{n}\),不妨看作是\(\sqrt{n}\)。由于有n个数,所以时间复杂度是\(O(n\sqrt{n})\)
于是就变成了\(O(n\sqrt{n})\)了。

详细过程见代码:

#include<algorithm>
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<math.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=50010;
typedef long long ll;
ll num[maxn],up[maxn],dw[maxn],ans,aa,bb,cc;
int col[maxn],pos[maxn];
struct qnode
{int l,r,id;
} qu[maxn];
bool cmp(qnode a,qnode b)
{if(pos[a.l]==pos[b.l])return a.r<b.r;return pos[a.l]<pos[b.l];
}
ll gcd(ll x,ll y)
{ll tp;while(tp=x%y){x=y;y=tp;}return y;
}
void update(int x,int d)
{ans-=num[col[x]]*num[col[x]];num[col[x]]+=d;ans+=num[col[x]]*num[col[x]];
}
int main()
{int n,m,i,j,bk,pl,pr,id;freopen("in.txt","r",stdin);while(~scanf("%d%d",&n,&m)){memset(num,0,sizeof num);bk=ceil(sqrt(1.0*n));for(i=1;i<=n;i++){scanf("%d",&col[i]);pos[i]=(i-1)/bk;}for(i=0;i<m;i++){scanf("%d%d",&qu[i].l,&qu[i].r);qu[i].id=i;}sort(qu,qu+m,cmp);pl=1,pr=0;ans=0;for(i=0;i<m;i++){id=qu[i].id;if(qu[i].l==qu[i].r){up[id]=0,dw[id]=1;continue;}if(pr<qu[i].r){for(j=pr+1;j<=qu[i].r;j++)update(j,1);}else{for(j=pr;j>qu[i].r;j--)update(j,-1);}pr=qu[i].r;if(pl<qu[i].l){for(j=pl;j<qu[i].l;j++)update(j,-1);}else{for(j=pl-1;j>=qu[i].l;j--)update(j,1);}pl=qu[i].l;aa=ans-qu[i].r+qu[i].l-1;bb=(ll)(qu[i].r-qu[i].l+1)*(qu[i].r-qu[i].l);cc=gcd(aa,bb);aa/=cc,bb/=cc;up[id]=aa,dw[id]=bb;}for(i=0;i<m;i++)printf("%I64d/%I64d\n",up[i],dw[i]);}return 0;
}

转载于:https://www.cnblogs.com/P6174/p/7723856.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/268215.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网站服务器被别人绑定域名了怎么办(nginx)?

为什么80%的码农都做不了架构师&#xff1f;>>> 网站服务器被别人绑定域名了怎么办&#xff08;nginx&#xff09;? 解决办法 两种解决方案&#xff1a;nginx 的默认虚拟主机在用户通过IP访问 &#xff0c;或者通过未设置的域名 访问&#xff08;比如有人把他自己…

Error:fatal: Not a git repository (or any of the parent directories): .git

在项目目录下执行git init命令。 大功告成。转载于:https://www.cnblogs.com/diyishijian/p/7724866.html

Discuz二次开发基本知识

一&#xff09; Discuz!的文件系统目录注&#xff1a;想搞DZ开发&#xff0c;就得弄懂DZ中每个文件的功能。a) Admin&#xff1a;后台管理功能模块b) Api&#xff1a;DZ系统与其它系统之间接口程序c) Archiver&#xff1a;DZ中&#xff0c;用以搜索引擎优化的无图版d) Attachme…

【bzoj2326】[HNOI2011]数学作业 矩阵乘法

题目描述 题解 矩阵乘法 考虑把相同位数的数放到一起处理&#xff1a; 设有$k$位的数为$[l,r]$&#xff0c;那么枚举从大到小的第$i$个数&#xff08;即枚举$r-i1$&#xff09;&#xff0c;考虑其对$Concatenate(l..r)$的贡献&#xff1a; $v_i(r-i1)10^{k(i-1)}$ 所以要求的就…

docker search 镜像名 从仓库查找镜像

docker search 使用 想要从仓库查找镜像

ffmpeg文档6:同步音频

指导6&#xff1a;同步音频 同步音频 现在我们已经有了一个比较像样的播放器。所以让我们看一下还有哪些零碎的东西没处理。上次&#xff0c;我们掩饰了一点同步问题&#xff0c;也就是同步音频到视频而不是其它的同步方式。我们将采用和视频一样的方式&#xff1a;做一个内部视…

Jzoj4778 数列编辑器

我们发现前四个操作可以用双向链表维护&#xff0c;而最后一个操作有一个限制就是1<k<n&#xff0c;所以可以用一个数组存在光标前面的数&#xff0c;每次维护一下前缀和就好 #include<stdio.h> #include<string.h> #include<algorithm> #define N 100…

Error response from daemon: conflict: unable to delete acdcfe83bcc5 (must be forced) - image is bein

报错如下&#xff0c;使用docker rmi 镜像名 报错了 Error response from daemon: conflict: unable to delete acdcfe83bcc5 (must be forced) - image is being used by stopped container 79e028dc2cbf 解决方法&#xff1a; 加上-f参数&#xff0c;表示强制删除 使用doc…

.NET 并行(多核)编程系列之六 Task基础部分完结篇

.NET 并行(多核)编程系列之六 Task基础部分完结篇 前言&#xff1a;之前的文章介绍了了并行编程的一些基本的&#xff0c;也注重的讲述了Task的一些使用方法&#xff0c;本篇很短&#xff0c;将会结束Task的基础知识的介绍。 本篇的主要议题如下: 1. 获取Task的状态 2. …

Sring AOP(简记)

什么是AOP AOP&#xff08;Aspect-OrientedProgramming&#xff0c;面向方面编程&#xff09;&#xff0c;可以说是OOP&#xff08;Object-Oriented Programing&#xff0c;面向对象编程&#xff09;的补充和完善。OOP允许你定义从上到下的关系&#xff0c;但并不适合定义从左到…

docker 什么是虚悬镜像

什么是虚悬镜像 仓库名、标签都是 none的镜像就是虚悬镜像(dangling image) 这种镜像需要删除&#xff0c;根据镜像ID删除该虚悬镜像 docker rmi -f [IMAGE ID]

2010年06月12日

为什么80%的码农都做不了架构师&#xff1f;>>> 今天装了个rhel 5.5,想制定光盘做yum源&#xff0c;网上找了个资料&#xff1a; rhel 5.x 将YUM指定为光盘--yum配置格式示例 后经过自己测试发现&#xff0c;只需要&#xff1a; 1. mount -o loop rhel-5-server-dv…

2017.10.25

日期计算 时间限制&#xff1a;3000 ms | 内存限制&#xff1a;65535 KB难度&#xff1a;1描述如题&#xff0c;输入一个日期&#xff0c;格式如&#xff1a;2010 10 24 &#xff0c;判断这一天是这一年中的第几天。输入第一行输入一个数N&#xff08;0<N<100&#xff…

如何现实CITRIX XenAPP内容重定向

在使用CITRIX XenAPP为用户交付各大应用时&#xff0c;我们会让到一个问题&#xff0c;比如说&#xff0c;我采用XENAPP交付给用户了MS-OFFICE WORD应用&#xff0c;而此用户在他本机并未安装任何的OFFICE 版本&#xff0c;那么&#xff0c;当用户在打开*.doc/*.docx文件时&…

JAVA-初步认识-第八章-继承-单继承和多重继承

一. 说完了继承的基本概述之后&#xff0c;了解一下在java中它的体现方式。 大家都知道java来自于c&#xff0c;c有多继承&#xff0c;java对其中的多继承进行了改良。为什么不直接支持多继承呢&#xff1f;要牢记&#xff0c;这个原因在后面可以解决很多问题。 二. 观看下面的…

docker重启容器

docker restart 容器id

让你的Silverlight程序部署在任意服务器上

今天在CSDN上逛&#xff0c;看到一篇不错的教程贴&#xff0c;“让你的SilverLight程序部署在任意服务器上”&#xff0c;转到园子里&#xff0c;希望更多朋友受益。 即使是免费的只支持HTML的空间&#xff0c;同样可以部署SilverLight应用。众所周知&#xff0c;SilverLight的…