B Beauty Values 2019牛客暑假多校第八场 (规律)

原题链接:Beauty Values

题意:给你一个序列,让你求出 所有子区间的不同数字的个数 总和
思路:或许有人跟我一样第一时间想到主席数这类的统计区间不同数个数(..好吧就当我这样),然而看到榜上过了那么多人在怎么说也不会再往那边想了,肯定是有规律的。
我在分析这个区间不同个数的时候发现某个数对区间的贡献范围。比如样例中 1 2 1 3 我们会发现 第二个 1 在区间[2,4]以及其子区间在统计个数的时候算一个贡献
即在其距离左右两端的相同的数字的大区间内算一个贡献(其他区间的1不会影响) ,然后我们这样思考后会发现如果更大的区间,比如[1,4]应该算谁的贡献。

实际上我们可以算作区间最左或者最右的值产生的贡献。我们固定一个按最左来产生贡献(这样不会重复统计)
即某个位置pos的值产生贡献区间范围在[i+1,n] (i为上一个出现的位置,n为长度)。 然后计算 子区间个数。我们这样看  1 2 1 3 上计算 第二个1 的贡献值即[2,4], [2,3],[3,4],[3,3]

所以我们发现即时左边断点在[i+1,pos]之间右边端点在[pos,n]之间。所以最后 我们可以得到关系式:( pos - i ) * (n - pos + 1)//这里下标我是从1开始记录,左端点设为0

像我这种菜鸡估计才会把这么简单的题写详细题解吧...TAT

code:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5+5;
ll arr[maxn];
int cur[maxn];
ll ans;
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>arr[i];
    }
    ll L;
    ans = 0;
    memset(cur,0,sizeof(cur));
    for(int i=1;i<=n;i++){
        ans += (ll)(i-cur[arr[i]]) * (n-i+1);
        cur[arr[i]] = i;
    }
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Tianwell/p/11367072.html