题目描述
Gromah and LZR have entered the second level. There is a sequence a_1, a_2, \cdots, a_na1,a2,⋯,an on the wall.
There is also a note board saying "the beauty value of a sequence is the number of different elements in the sequence".
LZR soon comes up with the password of this level, which is the sum of the beauty values of all successive subintervals of the sequence on the wall.
Please help them determine the password!
输入描述:
The first line contains one positive integer n_{}n, denoting the length of the sequence.
The second line contains n_{}n positive integers a_1, a_2, \cdots, a_na1,a2,⋯,an, denoting the sequence.
1 \le a_i \le n \le 10^51≤ai≤n≤105
输出描述:
Print a non-negative integer in a single line, denoting the answer.
输入
4
1 2 1 3
输出
18
题意:求数组中所有区间内不同元素的种类的和
思维题,找了半天规律,大致如下:
数组 1 12 123 1234 12345
种类和 1 4 10 20 35
跨度 3 6 10 15
种类和的跨度存在着规律,即加上新增元素的下标(从1开始)
而当出现一位前面存在的数字时,又有这样的规律:
数组 1 12 121 1212 12121
种类和 1 4 9 16 25
跨度 3 6 10 15
恒减值 0 0 1 3 6
即加入一位出现过的数字时,种类和=种类和+跨度-恒减值
恒减值即为前面最近出现过的数字下标的累加
如第三次出现1时,与第一位的1重复,那么加上他的下标1,
第四次出现2时,与第二位的2重复,加上下标2,
第五次出现1时,此时只计算前面最近的1,也就是第三个1的下标3,
这里的恒减值实际上就是加入一位新元素时,计算的时候又把前面重复的元素算了一遍,所以记录下来每次减去这个值
如果不明白的话可以自己模拟一下
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
ll a[100005];
ll k[100005];//跨度
ll b[100005];//出现过下标和
int main()
{
int n,i;
ll x=0,s=0;
mem(b,0);
cin>>n;
k[0]=0;
for(i=1;i<=n;i++)
{
cin>>a[i];
k[i]=k[i-1]+i;
}
for(i=1;i<=n;i++)
{
int t=a[i];
if(b[t])
x+=b[t];
s+=k[i]-x;
b[t]=i;
}
cout<<s<<endl;
return 0;
}