SCUT校赛129:笔芯值(数学)

来源:互联网 发布:微控触摸屏软件 编辑:程序博客网 时间:2024/04/28 02:07

题目描述

对于一个nn个数的序列 a_1,a_2,\cdots,a_na1,a2,,an,从小到大排序之后为a_{p_1},a_{p_2},\cdots,a_{p_n}ap1,ap2,,apn,定义它的 bxbx 值为满足 a_{p_i} \neq a_{p_{i-1}}+1, 1 < i \leq napiapi1+1,1<in 的 ii 的个数。

给定 nn 个数的一个排列,你需要计算它所有连续子序列的 bxbx 值之和。


输入格式

输入第一行包括一个正整数 TT,表示数据组数。
对于每组数据,第一行一个整数 nn,第二行 nn 个整数,表示 nn 个数的一个排列。
1 \leq T \leq 201T20
1 \leq n \leq 1000001n100000
1 \leq a_i \leq n1ain


输出格式

对每组数据输出一个整数表示答案。


样例数据

输入

231 2 343 1 4 2

输出

05

思路:先计算n个数总的bx值,连续子序列长度为x对答案做出的贡献为(n-(x-1))*(x-1),再减去非法的个数。具体做法就是对这n个数的下标排序,连在一起的下标就是非法的,比如a[3] = 7,a[6] = 8,那么包含下标3和6的连续子序列都需要减去1,那么这样的序列有3*(n-6+1)个。

# include <bits/stdc++.h># define ll long longusing namespace std;const int maxn = 1e5;ll a[maxn+3];int c[maxn+3];int main(){    int t, n;    scanf("%d",&t);    while(t--)    {        ll ans = 0;        scanf("%d",&n);        for(int i=1; i<=n; ++i)        {            scanf("%d",&a[i]);            c[a[i]] = i;            ans += (ll)(n-i+1)*(i-1);        }        for(int i=1; i<n; ++i)        {            int l = c[i], r = c[i+1];            if(l > r) swap(l, r);            ans -= (ll)l*(n-r+1);        }        printf("%lld\n",ans);    }    return 0;}


0 0