给定一个数组a1 a2 an。计算元组(i, j, k, l)的个数,使:一个& lt; i; rolelabel j & lt; k & lt; l; rolelabel n;ai = ak 和 aj = at;输入第一行包含一个整数t (1 <t< 100)——测试用例的数量。每个测试用例的第一行包含一个整数n (4 <n < 3000)——数组a的大小。每个测试用例的第二行包含n个整数a1, a2,.., an (1 S ai S n)-数组a。可以保证一次测试中n的和不超过3000。输出对于每个测试用例,打印描述的元组的数量。
Example
input
Copy
2 5 2 2 2 2 2 6 1 3 3 1 2 3
output
Copy
5 2
请注意在第一个测试用例中,对于任意四个指标i < j < k < l都是有效的,因此答案是元组的数量。在第二个测试用例中,有两个有效的元组:(1,2,4,6): a1 = a4, a2 = a6;(1,3,4,6): a1 = a4, a3 = a6。
题解:
正常枚举四个端点肯定不行,如何能优化成n^2,可以两两配对
ai = ak aj = al
这样先来记录前面的[ai,aj]出现次数,然后遍历后面[ak,al]加上之前出现过的即可
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
#define int long long
int cnt[3005][3004];
int a[3005];
int ma = 3001;
void solve()
{
int n;
cin >> n;
memset(cnt,0,sizeof cnt);
map<PII,int> f;
for(int i = 1;i <= n;i++)
cin >> a[i];
int ans = 0;
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= i - 2;j++)
{
cnt[a[j]][a[i - 1]]++;
}
for(int j = i + 1;j <= n;j++)
{
ans += cnt[a[i]][a[j]];
}
}
cout << ans <<"\n";
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int t = 1;
cin >> t;
while(t--)
{
solve();
}
}