当前位置: 首页 > news >正文

提高:RMQ问题:【例 3】与众不同

时间限制 : 1 秒

内存限制 : 512 MB

A 是某公司的 CEO,每个月都会有员工把公司的盈利数据送给 A,A 是个与众不同的怪人,A 不注重盈利还是亏本,而是喜欢研究「完美序列」:一段连续的序列满足序列中的数互不相同。

A 想知道区间 [L,R] 之间最长的完美序列长度。

输入

第一行两个整数 N,M,N 表示连续 N 个月,编号为 0 到 N−1,M 表示询问的次数;

第二行 N 个整数,第 i 个数表示该公司第 i 个月的盈利值 aii​ ;

接下来 M 行每行两个整数 L,R,表示 A 询问的区间。

输出

输出 M 行,每行一个整数对应询问区间内的完美序列的最长长度。

样例
输入
9 2
2 5 4 1 2 3 6 2 4
0 8
2 6
输出
6
5
提示

数据范围与提示:

对于全部数据,1≤N,M≤2×10^5,0≤L≤R≤N−1,∣ai∣≤10^6。


详细注释版代码:

/*
1.先处理每个位置的最长不重复子序列的长度
2.RMQ是从i位置向右跳2^j
假设以len[i]为i结尾的最长不重复子序列的长度
结尾是i,长度是len[i],起点是i-len[i]+1
*/
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+2;
int a[N],len[N],dp[N][20],n,m,l,r;
unordered_map<int,int> lastpos;
int main()
{scanf("%d%d",&n,&m);for(int i=0;i<n;i++) scanf("%d",&a[i]);int l=0;for(int r=0;r<n;r++){//如果当前元素出现过,且最后一次出现的位置在窗口内 if(lastpos.count(a[r])){//l=前面出现过的a[r]这个数字的后面的+1位置//由于lastpos是全局保存的所以可能有a[r]这个数字出现在l之前 //所以需要max l=max(l,lastpos[a[r]]+1); }len[r]=r-l+1;//当前窗口的长度 lastpos[a[r]]=r;//更新当前元素的最新位置 }//RMQfor(int i=0;i<n;i++) dp[i][0]=len[i];for(int j=1;j<18;j++)for(int i=0;i+(1<<j)-1<n;i++)dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);while(m--){int a,b;scanf("%d%d",&a,&b);//二分int low=1,high=b-a+1,ans=0;while(low<=high){int mid=(low+high)/2;//计算对应子数组的结束位置//找长度为mid的子数组,其结束位置为l+mid-1;int endpos=a+mid-1;if(endpos>b){high=mid-1;continue;}//查询在[endpos,r]区间内是否存在len[r]>=mid的子数组//如果满足len[r]>mid,则确保子数组的左端点的左端一定在区间内 int maxx;if(endpos>b) maxx=0;else{int j=__lg(b-endpos+1);maxx=max(dp[endpos][j],dp[b-(1<<j)+1][j]);}if(maxx>=mid){//寻找更长的 ans=mid;low=mid+1;}else high=mid-1;}printf("%d\n",ans);}return 0;
}

无注释版代码:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+2;
int a[N],len[N],dp[N][20],n,m,l,r;
unordered_map<int,int> lastpos;
int main()
{scanf("%d%d",&n,&m);for(int i=0;i<n;i++) scanf("%d",&a[i]);int l=0;for(int r=0;r<n;r++){if(lastpos.count(a[r])) l=max(l,lastpos[a[r]]+1);len[r]=r-l+1;lastpos[a[r]]=r;}for(int i=0;i<n;i++) dp[i][0]=len[i];for(int j=1;j<18;j++)for(int i=0;i+(1<<j)-1<n;i++)dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);while(m--){int a,b;scanf("%d%d",&a,&b);int low=1,high=b-a+1,ans=0;while(low<=high){int mid=(low+high)/2;int endpos=a+mid-1;if(endpos>b){high=mid-1;continue;}int maxx;if(endpos>b) maxx=0;else{int j=__lg(b-endpos+1);maxx=max(dp[endpos][j],dp[b-(1<<j)+1][j]);}if(maxx>=mid){ans=mid;low=mid+1;}else high=mid-1;}printf("%d\n",ans);}return 0;
}

http://www.xdnf.cn/news/642385.html

相关文章:

  • 固态硬盘颗粒类型、选型与应用场景深度解析
  • 基于PySide6与pycatia的CATIA几何阵列生成器开发实践
  • 5.25 note
  • uni-app学习笔记十二-vue3中创建组件
  • ISO 20000体系:需求管理与容量管理含义与解释
  • 以下是修改Java版《我的世界》字体的分步指南(DeepSeek)
  • uni-app学习笔记十一--vu3 watch和watchEffect侦听
  • IntelliJ IDEA 中配置 Gradle 的分发方式distribution
  • jvm垃圾回收
  • github项目:llm-guard
  • 函数[x]和{x}在数论中的应用
  • 李沐《动手学深度学习》| 4.4 模型的选择、过拟合和欠拟合.md
  • STL的map和set(关联式容器深度解析)
  • 2025第三届黄河流域网络安全技能挑战赛--Crypto--WriteUp
  • 网络原理入门详解:从零理解互联网如何工作
  • Modbus协议原理
  • 【Hive 开发进阶】窗口函数深度解析:OVER/NTILE/RANK 实战案例与行转列高级技巧
  • Day02
  • springboot日志
  • NotePad++编辑Linux服务器文档
  • 安全权限管理:从零到精通Android动态权限请求机制
  • CV中常用Backbone-3:Clip/SAM原理以及代码操作
  • Spring Boot 项目中常用的 ORM 框架 (JPA/Hibernate) 在性能方面有哪些需要注意的点?
  • 2025年- H50-Lc158 --25. k个一组翻转链表(链表,双指针,虚拟头节点)--Java版
  • Muduo网络库流程分析
  • quill 富文本多张图片排序
  • SRS流媒体服务器之RTC播放环境搭建
  • 揭开C语言指针的神秘面纱:地址、变量与“指向”的力量
  • systemverilog的单精度浮点和双精度浮点
  • AI测试怎么做投入产出比分析以及人员分配?