Codeforces 905 (div2 C or div3 F) 题解
题目概述:在数组中取出一个连续的字串,如果该字串只在数组中出现过一次(注意:出现的含义是找不出另外一个字串和它全等,不管这个字串是连续的还是不连续的,如
4
2 3 2 1
其中 [2,1] 出现了两次,分别是下标[0,3]和下标[2,3],故子串(2,1)不符合条件)。算出有多少个子串是唯一的。
类型:双指针
要点注意:
1.如果该字串是唯一的话,应该满足两个条件中的其中一个。要么该字串的长度与其他字串的长度不同(所以数组本身就是一个唯一的字子串),要么该字串的长度与其他字串相同,但字串的内容不与其他字串全等。根据“用于检验的字串可以不连续”这个性质,我们可以发现,只有最左端出现的数字是从最左端开始第一次出现的 和 最右段出现的数字是从最右端开始第一次出现的 ,这个字串才是唯一的。所以我们可以通过这个特性来通过双指针,用O(N)的时间复杂度求出这道题。
//
// Created by Mrlaolu on 2024/1/14.
//
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N = 1010;
void solve()
{
int n;
cin >> n;
vector<int>a(n);
for(int i = 0;i < n;++i)
cin >> a[i];
map<int,int>checkl; //用来检查是不是第一次出现
vector<int>llac; //存数字第一次出现的位置
map<int,int>checkr;
vector<int>rlac;
for(int i = 0;i < a.size();++i)
{
if(!checkl[a[i]])
{
checkl[a[i]] = i + 1;
llac.push_back(i);
}
}
for(int i = a.size() - 1;i > -1;--i)
{
if(!checkr[a[i]])
{
checkr[a[i]] = i + 1;
rlac.push_back(i);
}
}
int sum = 0;
int r = rlac.size() - 1;
for(int l = 0;l < llac.size();++l)
{
while(llac[l] > rlac[r])
{
r--;
}
sum += r + 1;
}
cout << sum << endl;
}
signed main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
solve();
}
return 0;
}