链接:https://ac.nowcoder.com/acm/contest/18428/C
来源:牛客网
Arup has to make many practice questions for his Computer Science 1 students. Since many of the questions deal with arrays, he has to generate arrays for his students. Since he doesn’t want to give them difficult practice problems, he always guarantees that the arrays (given to the students) have unique values. Namely, no value will appear twice in any of his arrays.
Unfortunately, Arup is too lazy to generate arrays! About 20 years ago when he started teaching Computer Science 1, he made one really long array to reuse but this long array may have duplicate values. When he makes problems, he simply grabs a contiguous subsequence of this long array to be the array to be used for a problem but he needs to make sure the contiguous subsequence does not contain duplicates. If the long array has terms a[0], a[1], …, a[n-1], a contiguous subsequence of the long array is any sequence of j-i+1 terms a[i], a[i+1], …, a[j] where 0 ≤ i ≤ j ≤ n – 1.
Given an array of n integers, determine how many contiguous subsequences of the array do not contain any repeated values. Note that two subsequences with the same contents are considered different (i.e., both counted in the total) if they start at different locations of the original long array.
输入描述:
The first input line contains a single positive integer, n (1 ≤ n ≤ 1e5), representing the size of the input array. The following line contains n space separated integers, representing the values of the
input array, in the order they appear in the array. Each of the array values will be an integer between 1 and 1e18, inclusive.
(Note: 1e5 means 1 times 10 to the fifth power, that is, 100000)
输出描述:
On a line by itself, output the total number of contiguous subsequences of the input array that do not contain any repeated values.
示例1
输入
复制
5
1 1 2 1 5
输出
复制
9
示例2
输入
复制
8
2 12 3 12 3 2 6 9
输出
复制
22
题解:从第一个数开始,求其本身以及包含之前所有数的贡献,最后将总贡献加起来。
先考虑没有重复数时,1 2 3 sum(含不同数子序列的和)=1(1)+2(2,1 2)+3(3,2 3,1 2 3);即每个不同位置的数的贡献为其位置索引(从一开始)
有重复数时,1 1 2 1 5,同样的思路,只不过标记重复数出现的位置,并将其所在位置索引减去,具体操作自己根据题意搞,标记时建议用map,数组标记容易段错误(注意题目所给空间)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll nl=1e5+5;
map<ll,ll>v;//标记作用
ll a[nl];
int main(){
ll n;
cin>>n;
ll i,j;
for(i=0;i<n;i++){
cin>>a[i];
}
ll sum=0;
j=0;
for(i=0;i<n;i++){
if(v[a[i]]==0){//没有出现重复数
sum+=i+1-j;
v[a[i]]=i+1;
}else{
j=max(v[a[i]],j);//标记倒数第二次出现重复数的位置
sum+=i+1-j;
v[a[i]]=i+1;
}
}
cout<<sum;
}