LOJ #10121. 「一本通 4.2 例 3」与众不同
summarization
给出一个长度为 数列 和若干个询问,询问某一段区间内最长的「完美序列」的长度。(「完美序列」:一段连续的序列满足序列中的数互不相同)
solution
显然在一个数列的所有「完美序列」中,我们肯定可以找到若干个最长「完美序列」,使其余的「完美序列」都被这些最长的「完美序列」中的一个包含。所以考虑求出以第 个数结尾的最长的「完美序列」(),然后根据询问查找(后文会具体讲)。
那么设 为以第 个数结尾的最长的「完美序列」的起始位置; 为以第 个数结尾的最长的「完美序列」的长度,显然 ; 为 最近出现的位置。
很好维护,只要在遍历到第 个时,使 即可。 可以用递推的方法维护:。
然后处理询问,设询问区间为 :
由上式, 单调不减。于是我们一定可以找到一个 ,使 ,设此时的 为 。
那么 就可以分成两部分: 和 。
- :答案显然为 。
- :答案为 (是一个 RMQ 问题,可以 ST 表或者别的)
取个最大值。
PS:注意细节,如 的特殊位置。
code
CI N = 2e5, LGN = 20, E = 1e6; int n, m, a[N + 5], st[N + 5], len[N + 5], lst[N + 5], lg[N + 5], fa[N + 5][LGN + 5];
int ask (int l, int r) {
int L = l, R = r, ans = r + 1, now = 0; W (L <= R) {int mid = (L + R) >> 1; if (st[mid] >= l) ans = mid, R = mid - 1; else L = mid + 1;}
if (ans > l) now = ans - l; if (ans <= r) {int k = lg[r - ans + 1]; now = max (now, max (fa[ans][k], fa[r - (1 << k) + 1][k]));} return now;
}
int main () {
RI i, j; for (Read (n, m), i = 1; i <= n; ++ i) Read (a[i]); for (i = 2; i <= n; ++ i) lg[i] = lg[i >> 1] + 1;
for (i = 1; i <= n; ++ i) st[i] = max (st[i - 1], lst[E + a[i]] + 1), len[i] = i - st[i] + 1, lst[E + a[i]] = i, fa[i][0] = len[i];
for (j = 1; j <= lg[n]; ++ j) for (i = 1; i <= n - (1 << j) + 1; ++ i) fa[i][j] = max (fa[i][j - 1], fa[i + (1 << j - 1)][j - 1]);
for (i = 1; i <= m; ++ i) {int x, y; Read (x, y); printf ("%d\n", ask(x + 1, y + 1));}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探