专栏文章

题解:AT_abc390_f [ABC390F] Double Sum 3

AT_abc390_f题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miqe4zse
此快照首次捕获于
2025/12/04 03:19
3 个月前
此快照最后确认于
2025/12/04 03:19
3 个月前
查看原文
根据题目描述,可以发现 f(L,R)f(L,R) 其实就是 AL,AL+1ARA_L,A_{L+1}\dots A_R 中的数组成的极长值域连续段数。
我们考虑扫描右端点 rr,同时维护每个左端点的 f(l,r)f(l,r)
每次左端点右移,那么 f(l,r)f(l,r) 会变成 f(l,r+1)f(l,r+1),其实就是添加一个数 Ar+1A_{r+1},那么会造成什么影响呢?
假设 Ar+1A_{r+1} 之前未出现过,那么添加之后:
  • Ar+11A_{r+1}-1Ar+1+1A_{r+1}+1 均未出现,那么极长值域连续段数加一。
  • 若出现其一,Ar+1A_{r+1} 会被相邻的极长值域连续段吸收,那么极长值域连续段数不变。
  • 若均出现,那么发生极长值域连续段的合并,极长值域连续段数减一。
那么我们开一个数组 preipre_i 代表数字 ii 上一次出现的位置,每次加入数字 x=Arx=A_{r} 时,记 a=min(prex1,prex+1),b=max(prex1,prex+1)a=\min(pre_{x-1},pre_{x+1}),b=\max(pre_{x-1},pre_{x+1})
  • 对于 [1,prex][1,pre_{x}],没有任何影响。
  • 对于 [prex+1,a][pre_x+1,a],会发生 x1x-1 所在极长值域连续段和 x+1x+1 所在极长值域连续段的合并,使极长值域连续段数减一。
  • 对于 [a+1,b][a+1,b]xx 会并入x1x-1 所在极长值域连续段或 x+1x+1 所在极长值域连续段,答案没有变化。
  • 对于 [b+1,r][b+1,r]xx 不会被吸收,极长值域连续段数加一。
做法已经呼之欲出了,从左向右扫描右端点的同时维护 sum=l=1rf(l,r)sum=\sum\limits_{l=1}^rf(l,r) ,同时用 ansans 进行累加。
CPP
#include <bits/stdc++.h>
#define LL long long
using namespace std;

inline LL read()
{
	LL x = 0,f = 1;char ch = getchar();
	while(!isdigit(ch)) (ch == '-') && (f = -1),ch = getchar();
	while(isdigit(ch)) x = x*10+ch-48,ch = getchar();
	return x*f;
}

const int N = 3e5+5;
int a[N],pre[N];

int main()
{
	int n = read();
	LL ans = 0,sum = 0;
	for (int i = 1;i <= n;i++)
	{
		a[i] = read();
		int x = max(pre[a[i]-1],pre[a[i]]),y = max(pre[a[i]+1],pre[a[i]]);
		if (x > y) swap(x,y);
		sum = sum+i-y-(x-pre[a[i]]),ans += sum;
		pre[a[i]] = i;
	}
	cout << ans;
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...