LOJ #10121. 「一本通 4.2 例 3」与众不同

链接:#10121. 「一本通 4.2 例 3」与众不同

summarization

给出一个长度为 n 数列 a 和若干个询问,询问某一段区间内最长的「完美序列」的长度。(「完美序列」:一段连续的序列满足序列中的数互不相同)

solution

显然在一个数列的所有「完美序列」中,我们肯定可以找到若干个最长「完美序列」,使其余的「完美序列」都被这些最长的「完美序列」中的一个包含。所以考虑求出以第 i 个数结尾的最长的「完美序列」(1in),然后根据询问查找(后文会具体讲)。

那么设 sti 为以第 i 个数结尾的最长的「完美序列」的起始位置; leni 为以第 i 个数结尾的最长的「完美序列」的长度,显然 leni=isti+1lstxx 最近出现的位置。

lstx 很好维护,只要在遍历到第 i 个时,使 lstai=i 即可。sti 可以用递推的方法维护:sti=max(sti1,lstai+1)

然后处理询问,设询问区间为 [l,r]:

由上式,sti 单调不减。于是我们一定可以找到一个 i,使 stil,sti1<l,设此时的 imid

那么 [l,r] 就可以分成两部分:[l,mid1][mid,r]

  • [l,mid1]:答案显然为 midl
  • [mid,r]:答案为 maxi=midrleni(是一个 RMQ 问题,可以 ST 表或者别的)

取个最大值。

PS:注意细节,如 mid 的特殊位置。

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; 
}
posted @   ClapEcho233  阅读(74)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探
点击右上角即可分享
微信分享提示