专栏文章
题解: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 个月前
根据题目描述,可以发现 其实就是 中的数组成的极长值域连续段数。
我们考虑扫描右端点 ,同时维护每个左端点的 。
每次左端点右移,那么 会变成 ,其实就是添加一个数 ,那么会造成什么影响呢?
假设 之前未出现过,那么添加之后:
- 若 和 均未出现,那么极长值域连续段数加一。
- 若出现其一, 会被相邻的极长值域连续段吸收,那么极长值域连续段数不变。
- 若均出现,那么发生极长值域连续段的合并,极长值域连续段数减一。
那么我们开一个数组 代表数字 上一次出现的位置,每次加入数字 时,记 。
- 对于 ,没有任何影响。
- 对于 ,会发生 所在极长值域连续段和 所在极长值域连续段的合并,使极长值域连续段数减一。
- 对于 , 会并入 所在极长值域连续段或 所在极长值域连续段,答案没有变化。
- 对于 , 不会被吸收,极长值域连续段数加一。
做法已经呼之欲出了,从左向右扫描右端点的同时维护 ,同时用 进行累加。
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 条评论,欢迎与作者交流。
正在加载评论...