热门标签 | HotTags
当前位置:  开发笔记 > 人工智能 > 正文

题解SP3267【DQUERYDquery】

题目描述:给出一串长度为\(n\)的序列,有\(q\)个询问,每次询问给数对\((i,j)\),求区间\([i,j]\)中有多少个不同的数字这题我是用莫队过的;众所周知,莫队是一个

题目描述:

给出一串长度为 \(n\) 的序列,有 \(q\) 个询问,每次询问给数对 \((i,j)\),求区间 \([i,j]\) 中有多少个不同的数字



这题我是用莫队过的;

众所周知,莫队是一个暴力毒瘤玄学很方便的算法(不套其他的数据结构),可以乱搞很多的区间问题。

p.s.我是通过这篇博客来自学的,如果有理解不对的地方,还望 dalao 指正



进入正题:

莫队算法将询问排序后,通过移动左右端点来更改答案,从而保证它优秀的复杂度。

在排序询问时,我们要用到分块的思想:

我们将整个区间分成 \(\sqrt{n}\) 个块。

在排序的时候,如果左端点在同一个块,就将右端点按从大到小排序;否则,按左端点的块从大到小排序。

这样保证了每个端点一次最多移动 \(\sqrt{n}\) 格,从而保证了复杂度。

friend bool operator <(qus a,qus b){
return k[a.l]==k[b.l]?a.r}

然后在排序的时候可以将普通的排序,换成按块的奇偶分类排序,可以让你的代码玄学咕咕咕的加快。

friend bool operator <(qus a,qus b){
return k[a.l]^k[b.l]?k[a.l]b.r);
}

之后便是 AddDel 函数,用来在移动的同时更新答案。

用 num 来记录目前的区间 \([l,r]\) 的数字种类,\(cnt_x\) 来记录 x 出现的次数;

在加入第 pos 个数时,如果该数在这个区间第一次出现,则将总数加一:

void Add(int pos){
if(!cnt[a[pos]]) ++num;
++cnt[a[pos]];
}

在删除第 pos 个数时,如果删除后这个数在区间内不在出现,则将总数减一:

void Del(int pos){
--cnt[a[pos]];
if(!cnt[a[pos]]) --num;
}

然后是转移左右端点。

如果当前的左端点,小于答案的左端点,则将该点删除,并将左端点向右移;

如果当前的左端点,大于答案的左端点,则将左端点左移,并且将该点加入;

如果当前的右端点,大于答案的右端点,则将该点删除,并将右端点向左移;

如果当前的右端点,小于答案的右端点,这将右端点右移,并且将该点加入。

(这不是绕口令)

while(L while(L>q[i].l) Add(--L);
while(R while(R>q[i].r) Del(R--);

最后在统计答案的时候,按照原先输入的顺序输出就好了。



代码如下(码风有点丑):

#include
#define rint register int
using namespace std;
inline int read(){
int s=0,f=1; char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=0;c=getchar();}
while(c>='0'&&c<='9') s=(s<<1)+(s<<3)+(c^48),c=getchar();
return f?s:-s;
}
int n,a[30010],cnt[1000010],num=0,Q;
int k[1010],ks,ans[200010];
struct qus{
int l,r,id;
friend bool operator <(qus a,qus b){
return k[a.l]^k[b.l]?k[a.l]b.r);
}
}q[200010];
void Del(int pos){
--cnt[a[pos]];
if(!cnt[a[pos]]) --num;
}
void Add(int pos){
if(!cnt[a[pos]]) ++num;
++cnt[a[pos]];
}
int main(){
n=read(); ks=sqrt(n);
for(rint i=1;i<=n;++i) a[i]=read();
for(rint i=1;i<=n;++i) k[i]=(i-1)/ks+1;
Q=read();
for(rint i=1;i<=Q;++i){
q[i].l=read();
q[i].r=read();
q[i].id=i;
}
sort(q+1,q+1+Q);
int L=1,R=0;
for(rint i=1;i<=Q;++i){
while(L while(L>q[i].l) Add(--L);
while(R while(R>q[i].r) Del(R--);
ans[q[i].id]=num;
}
for(rint i=1;i<=Q;++i)
printf("%d\n",ans[i]);
return 0;
}

咕咕咕~



推荐阅读
  • 通过一张截图深入解析字节跳动的 Java 开发实力
    在与一位来自字节跳动的朋友交流时了解到,根据他们近期招聘Java工程师的经验,大多数候选人往往在工作3年后会遇到一个难以跨越的瓶颈期。这是因为在职业生涯的这个阶段,许多工程师的技术深度和广度已经达到了一定的水平,但要进一步提升则需要更多的挑战和学习机会。字节跳动作为一家技术驱动的公司,通过严格的面试流程和实际项目经验,能够更好地评估候选人的技术水平和发展潜力。 ... [详细]
  • 深入理解JavaScript中的原型和原型链机制
    在JavaScript中,原型和原型链是核心概念。通过定义构造函数`function Foo() {}`,可以创建实例对象`let f1 = new Foo()`。继承机制主要依赖于每个函数都具有的`prototype`属性,除了内置的`Function`构造函数之外,这一特性使得对象间的属性和方法共享成为可能。原型链通过链接这些原型对象,实现了复杂而灵活的继承结构,为JavaScript的面向对象编程提供了坚实的基础。 ... [详细]
  • 深入解析MySQL Replication中的并行复制机制与实例应用【MySQL进阶教程】
    本文深入探讨了MySQL 5.6版本后引入的并行复制机制,详细解析了其工作原理及优化效果。通过具体实例,展示了如何在实际环境中配置和使用并行复制,以提高数据同步效率和系统性能。 ... [详细]
  • 贪心算法在经典问题中的多种应用实例分析
    本文深入探讨了贪心算法在多个经典问题中的应用实例,通过具体案例分析,展示了该算法在解决优化问题时的有效性和灵活性。同时,文章还结合Go语言的特点,为Golang开发者提供了实用的编程技巧和经验分享。 ... [详细]
  • 网上报名提交电子照片时,如何调整文件大小以满足30K至200K的要求?
    随着互联网实名制的普及,许多在线服务都需要用户上传个人照片。然而,在提交电子照片时,经常遇到文件大小不符合要求的问题。本文将详细介绍如何调整照片文件大小,确保其在30K至200K之间,以满足各种网上报名和实名认证的需求。通过使用图像处理软件或在线工具,用户可以轻松压缩或优化照片,确保顺利提交。此外,文章还将提供一些实用技巧,帮助用户在保持图片质量的同时,达到所需的文件大小。 ... [详细]
  • 本文详细探讨了快速排序算法的实现原理及其优化策略,通过具体代码示例 `function quickSort(arr, left, right)` 解析了数组在不同区间内的递归排序过程,旨在帮助读者深入理解快排的工作机制和性能优化方法。 ... [详细]
  • 比特币开发者在本周二通过随机选择的方式确定了Taproot激活的具体方案。最终决定采用平均通过时间(Median Time Past, MTP)算法来计算Taproot的激活时间线。这一调整旨在确保网络的稳定性和安全性,同时提高协议的灵活性和效率。 ... [详细]
  • 学术论文深度解析与评价
    本文深入探讨了基于摆线推进器的无人监测船系统的研发背景及其重要性。从环境保护的宏观视角出发,逐步聚焦至湖泊生态监测的具体需求,分析了现有生态监测技术的局限性,并提出了创新性的解决方案,旨在通过改进内部技术实现更高效、精准的生态环境监测。 ... [详细]
  • 本文探讨了一种高效的策略,用于将n个人合理分配到m个具有不同容量的房间中,确保每个房间至少有两人入住,同时最大化利用大容量房间的空间。 ... [详细]
  • 在JSP页面中调用客户端本地应用程序(例如 `C:\netterm.exe`)时,可以通过使用 `Runtime.getRuntime().exec("c:\\netterm.exe")` 实现。然而,这种方法仅在服务器端有效,若要实现在客户端执行本地程序,需要采用其他技术手段,如Java Applet或ActiveX控件,以确保安全性和兼容性。 ... [详细]
  • 题目 1449 砝码称重问题通过高效的贪心算法在 1 秒内成功解决。给定三种不同重量的砝码 \( w_0 \)、\( w_1 \) 和 \( w_2 \),每种砝码各有一个。本题要求判断是否能够使用这些砝码组合出一个特定的重量 \( m \)。通过示例解析,详细展示了如何利用贪心策略快速找到解决方案。 ... [详细]
  • 针对给定的二叉树,本文详细解析了如何实现从左至右、逐层遍历节点值的算法,并探讨了优化方法,以提高遍历效率和代码可读性。 ... [详细]
  • 基于遗传算法的MATLAB入门与应用指南
    遗传算法作为一种模拟自然界生物遗传和进化的自适应全局优化方法,在解决复杂优化问题中展现出显著优势。本文基于MATLAB平台,详细介绍了遗传算法的基本原理及其在求解NP难题、非线性及多峰函数优化、多目标优化等领域的应用实例,为初学者提供了一套系统的学习和实践指南。 ... [详细]
  • 在Maven中高效管理多模块项目的依赖关系是一项重要的技能。通过合理配置父POM文件,可以统一管理和控制各子模块的依赖版本,避免重复导入和版本冲突。本文将探讨如何利用Maven的最佳实践,确保项目依赖的一致性和可维护性,同时提高开发效率。 ... [详细]
  • 深入解析数据结构与算法:基数排序的原理与应用
    本文详细探讨了基数排序(Radix Sort)的基本原理及其应用场景。作为一种非比较型整数排序算法,基数排序通过将元素按照位数分配到不同的桶中进行排序,最终合并各个桶中的元素得到有序序列。文章首先介绍了基数排序的核心思想和工作流程,随后通过具体代码示例展示了其实现过程。此外,还对基数排序在处理大规模数据集时的性能表现进行了测试,并讨论了在实际应用中需要注意的事项。 ... [详细]
author-avatar
手机用户2502896257
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有