好的,我将这道题整理为清晰的题面格式,并补充样例解释、数据范围与时空限制:
题目描述
A 是某公司的 CEO,每个月都会有员工把公司的盈利数据送给 A,A 是个与众不同的怪人,A 不注重盈利还是亏本,而是喜欢研究「完美序列」:一段连续的序列满足序列中的数互不相同。
A 想知道区间 [L,R] 之间最长的完美序列长度。
输入格式
第一行两个整数 N,M,N 表示连续 N 个月,编号为 0 到 N−1,M 表示询问的次数;
第二行 N 个整数,第 i 个数表示该公司第 i 个月的盈利值 ai;
接下来 M 行每行两个整数 L,R,表示 A 询问的区间。
输出格式
输出 M 行,每行一个整数,对应询问区间 [L,R] 内最长的完美序列(连续且互不相同)的长度。
样例
样例输入
9 2
2 5 4 1 2 3 6 2 4
0 8
2 6
样例输出
6
5
样例说明
N=9,序列 [2,5,4,1,2,3,6,2,4]。
询问1:区间 [0,8](整个序列)中最长完美序列:
- 从下标 2 开始:[4,1,2,3,6](长度 5)
- 从下标 3 开始:[1,2,3,6,2,4](长度 6,但有两个 2 重复,实际上 [1,2,3,6] 长度 4)
- 正确的最长完美序列:从下标 2 到 6:[4,1,2,3,6] 长度 5,还是从下标 3 到 8:[1,2,3,6,2,4] 有重复,所以最长可能是 5?但样例输出是 6。
我们检查:从下标 3 到 8 的序列 [1,2,3,6,2,4] 中下标 4 和 7 都是 2,重复了,所以不是完美序列。
实际上最长完美序列:从下标 0 到 5:[2,5,4,1,2,3] 也有重复 2,不是。
仔细找:从下标 1 到 6:[5,4,1,2,3,6] 长度 6,没有重复,这就是答案 6。
询问2:区间 [2,6] 的序列 [4,1,2,3,6] 长度 5,没有重复,所以输出 5。
数据范围
对于全部数据:
- 1≤N,M≤2×105
- 0≤L≤R≤N−1
- ∣ai∣≤106
时空限制
- 时间:1000 ms
- 内存:524288 KB(512 MB)
提示
此题为 区间内最长无重复子段 问题,可以离线用 RMQ + 预处理 或 ST 表 + 二分 解决。
预处理:
-
对于每个位置 i,计算 nxt[i]:以 i 为起点的最长无重复子段的结束位置的下一个位置(即 [i,nxt[i]−1] 无重复,但 nxt[i] 处重复或越界)。
这可以用双指针(尺取法)在 O(N) 内求出:
- 用
map 或数组(值域需离散化)记录每个值最后出现的位置 last;
- 遍历右端点 r,维护左端点 l,使得 [l,r] 无重复;
- 则 nxt[l]=r+1,然后 l 右移。
但更常用的是:设 f[i] 表示以 i 结尾的最长无重复子段的起始位置,可以通过 f[i]=max(f[i−1],last[a[i]]+1) 递推,其中 last[a[i]] 是 a[i] 上一次出现的位置。
那么 len[i]=i−f[i]+1 就是以 i 结尾的最长无重复子段长度。
-
但问题问的是区间 [L,R] 内的任意连续子段,不一定以 R 结尾。
我们可以先求出 st[i]:以 i 为起点的最长无重复子段的结束位置,即 st[i]=i+len−1,其中 len 是从 i 开始的无重复子段最大长度。
这个可以通过预处理 nxt[i] 得到:nxt[i] 表示从 i 开始的最远不重复位置(开区间),则 st[i]=nxt[i]−1。
但是区间查询时,可能答案被 R 截断。所以对于查询 [L,R]:
- 如果 st[L]≤R,说明从 L 开始的无重复子段完全在区间内,那么答案至少为 st[L]−L+1;
- 还需要考虑起点在 [L,R] 内的其他位置。
标准解法(离线 RMQ):
- 预处理 p[i]:以 i 结尾的最长无重复子段的起始位置(f[i] 如上);
- 对于询问 [L,R],我们需要找到 L≤x≤y≤R 使得 y−x+1 最大且 [x,y] 无重复。
- 由于无重复要求 f[y]≤x,所以对于固定的 y,x 至少为 f[y]。
- 因此,对于每个 y,对应的无重复子段为 [f[y],y],长度为 y−f[y]+1。
- 在区间 [L,R] 中,y 必须满足 f[y]≥L 且 y≤R。
- 问题转化为:在 [L,R] 中找 y,使得 y−f[y]+1 最大,但可能 f[y]<L,此时子段实际起点是 L,长度为 y−L+1。
- 因此,答案 = $\max\left( \max_{y \in [L,R], f[y] \ge L} (y-f[y]+1), \max_{y \in [L,R], f[y] < L} (y-L+1) \right)$。
简化做法:
预处理 len[i]=i−f[i]+1(以 i 结尾的最长无重复长度)。
对于询问 [L,R],找到第一个 t∈[L,R] 使得 f[t]≥L(即第一个完全在 [L,R] 内的无重复段),则:
- 对于 i∈[t,R],无重复段完全在 [L,R] 内,答案候选为 len[i];
- 对于 i∈[L,t−1],无重复段起点可能小于 L,实际长度为 i−L+1。
因此答案 = max(maxi=tRlen[i],t−L)(因为 i∈[L,t−1] 中最大 i−L+1 就是 t−L)。
于是问题变成:快速找到 t=min{i∈[L,R]∣f[i]≥L},可以用 二分 在 f 数组上查找(因为 f[i] 非降),然后用 RMQ 查询 [t,R] 中 len[i] 的最大值。
步骤:
- 预处理 f[i] 和 len[i](O(N));
- 对 f[i] 数组建立 ST 表用于二分查找第一个 f[i]≥L 的位置 t;
- 对 len[i] 建立 ST 表用于区间最大值查询;
- 对于每个询问 [L,R]:
- 二分找到 t;
- 若 t>R,则所有 f[i]<L,答案 =R−L+1;
- 否则答案 =max(t−L,RMQ(t,R))。
复杂度:预处理 O(NlogN),每个询问 O(logN)。
注意:ai 范围 [−106,106],需离散化或使用偏移数组记录最后出现位置。