C. You Are So Beautiful Codeforces Round 905 (Div. 2)

Problem - C - Codeforces

The main idea of ​​the question: There is an array a of length n. How many substrings [l, r] are there, such that this substring appears only once in a as a subsequence?

1<=n<=1e5;1<=a[i]<=1e9

Idea: We found that for the continuous interval starting from 1, the answers are non-decreasing, so we examine how the answer changes every time a number is added, and it will not affect the previous answer.

        So if we currently add a new number a[r], then the newly added legal answer count is the legal substring where a[r] is the right endpoint of the interval, that is, how many l's from 1 to r satisfy [l, r] is a legal interval. We found that for the previous number a[i], if it appears multiple times, then only the first time it appears is legal as the left endpoint of the interval. Any subsequent number can be used. is replaced by the number that appears for the first time, so the contribution of the number in each position is the number of the number that appears for the first time before it, then the contribution of each identical number is the number that appears before the last position How many first occurrences are there.

        To count the answer, we first record the last occurrence position of each number las[i], then traverse the array from left to right, record the number of the first occurrence of the number, and then if the current number is already at the position of the last occurrence of this number , just count the contribution of this number.

//#include<__msvc_all_public_headers.hpp>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 1e9 + 7;
const int N = 1e5 + 5;
int n;
int a[N];
void init()
{
	
}
void solve()
{
	map<int, int>las;
	cin >> n;
	init();
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		las[a[i]] = i;//记录每个数字最后一次出现的次数
	}
	ll ans = 0;
	ll cnt = 0;
	set<int>vis;
	for (int i = 1; i <= n; i++)
	{		
		if (vis.find(a[i]) == vis.end())
		{//第一次出现这个数字
			cnt++;//记录有多少个第一次出现的
			vis.insert(a[i]);
		}
		if (las[a[i]] == i)
		{//当前数字是最后一次出现的位置,统计贡献
			ans += cnt;
		}
	}
	cout << ans;
	cout << '\n';
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int t;
	cin >> t;
	//t = 1;
	while (t--)
	{
		solve();
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/ashbringer233/article/details/133978456