题解:AT_abc390_f [ABC390F] Double Sum 3

题面中进行的三个操作相当于:

  • 将集合 S={aiLiR} 划分为尽量少的集合的并集,其中每个集合包含一段连续整数。

注意到,一个连续整数段结束的标志是 xS(x+1)S。这意味着,无论 x 属于什么连续整数段,它的后继 y 一定属于一个新的段。因此,我们只需要统计每个整数 x 对多少个区间有贡献即可,即对于每个整数 x,统计有多少个区间中有 x 而没有 x+1

但这样依然不是很好统计,因为一个区间可能包含多个 x,容易数重或数漏。我们规定,每个符合要求的区间在其中包含的第一个 x 处被统计。

prei 为最大的 j<i 使得 Aj=xAj=x+1nxti 为最小的 j>i 使得 Aj=x+1。那么,任取 prei<LiiR<nxti,都满足 Ai 是区间 [L,R] 包含的第一个 x,且区间 [L,R] 不包含 x+1。这样的区间共有 (iprei)(nxtii) 个。

将每个 Ai 处的区间个数相加,答案即为 i=1n(iprei)(nxtii)

核心代码:

#define rep(x, y, z) for(ll x = (y); x <= (z); ++x)
#define per(x, y, z) for(ll x = (y); x >= (z); --x)

ll n, a[N], pos[N], pre[N], nxt[N], ans;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin >> n;
    rep(i, 1, n) cin >> a[i];
    rep(i, 1, n + 1) pos[i] = 0;
    rep(i, 1, n) {
        pre[i] = max(pos[a[i]], pos[a[i] + 1]);
        pos[a[i]] = i;
    }
    rep(i, 1, n + 1) pos[i] = n + 1;
    per(i, n, 1) {
        nxt[i] = pos[a[i] + 1];
        pos[a[i]] = i;
    }
    rep(i, 1, n) ans += (nxt[i] - i) * (i - pre[i]);
    cout << ans << endl;
    return 0;
}
posted @   rui_er  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2023-01-26 题解 CF1780G【Delicious Dessert】
2022-01-26 题解 CF1624F【Interacdive Problem】
点击右上角即可分享
微信分享提示