2019牛客暑期多校训练营(第八场)B-Beauty Values(期望线性性)

>传送门<

题意:
思路:期望的线性性(可加性)比赛的时候写的代码超级无敌长,不过值得欣慰的是一发AC了,官方的题解写的还不错~

我们可以把每种数字对答案的贡献分开来计算,即枚举每个数字,求原序列有多少个子区间包含至少一个该 数字,最后把答案累加起来即可。

问题在于求序列有多少个子区间包含至少一个某数字,既可以直接计算,也可以考虑用全集减去不包含的子区间。不包含的子区间的个数可以枚举相邻两个数字,并累加中间空隙的子区间个数,再统计一下边界即可。 时间复杂度为O(n)

下面给出直接计算的代码

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll v[100005];
int main()
{
    int n;
    cin>>n;
    ll ans = 0, a;
    for(int i=1;i<=n;i++){
        cin>>a;
        ans += (n-i+1)*(i-v[a]);
        v[a] = i;
    }
    cout<<ans<<endl; 
}

n-i+1表示的是当前数字a能影响到的后面区间数量,i-v[a](避免重复计算)表示的是当前a向左延伸直到上一个a间的区间数量+空区间,两者相乘即得到当前数字能影响到的区间,最后把每个数字相加起来就是答案。

举个栗子,就拿题目中的[1,2,1,3]来说

当扫描到i = 3时,这个1能影响到的区间有[3,3] = {1},[3,4] = {1,3},[2,3] = {2,1},[2,4] = {2,1,3},[1,3] = {1,2,1},[1,4] = {1,2,1,3}

但是你马上会发现此时这个1能影响到的区间和第一个1能影响的区间有一部分重合了,怎么办?

那我就只让这个1影响的区间向左扩散,直到碰到1就停下,即向左扩散只影响这两个1间的区间就行了

对于[7,6,2,1,3,4,1,5,9]而言

当i = 7,v[a] = 4(上一个a的位置),向后影响到9-7+1=3个区间( {1},{1,5},{1,5,9} ),向前影响到7-4=3个区间( {Ø},{2},{6,2},{7,6,2}),总共能影响到9个区间

原文地址:https://www.cnblogs.com/wizarderror/p/11340957.html