题意:长度为n(n<=3000)的序列a,求(i<j<k<l)且(a_i=a_k)且(a_j=a_l)的有序对(i,j,k,l)个数
很清晰明了的题面,时间不够没仔细琢磨
先尝试枚举一个位置,再用O(n)的复杂度统计答案,好像不太行..
再尝试枚举两个位置,枚举j和k,此时已经有O(n^2)的复杂度了,如何O(1)统计答案?
注意到j和k确定后,只需要在j左侧找等于a[k]的元素个数,在k右侧找等于a[j]的元素个数,二者相乘即完成了统计
暴力上n个前缀和、后缀和,f[i][j]表示前i位中j出现次数,p[i][j]表示i位以后j出现次数,O(n^2)预处理,O(1)统计就完了
对了,不开LL见祖宗
#include<bits/stdc++.h>
using namespace std;
inline int rd(){
int ret=0,f=1;char c;
while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
while(isdigit(c))ret=ret*10+c-'0',c=getchar();
return ret*f;
}
#define pc putchar
#define space() pc(' ')
#define nextline() pc('
')
void pot(int x){if(!x)return;pot(x/10);pc('0'+x%10);}
void out(int x){if(!x)pc('0');if(x<0)pc('-'),x=-x;pot(x);}
const int MAXN = 3005;
int n;
int a[MAXN];
int f[MAXN][MAXN];
int p[MAXN][MAXN];
void solve(){
memset(f,0,sizeof(f));
memset(p,0,sizeof(p));
n=rd();
for(int i=1;i<=n;i++) a[i]=rd();
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++) f[i][j]=f[i-1][j];
f[i][a[i]]++;
}
for(int i=n;i>=1;i--){
for(int j=1;j<=n;j++) p[i][j]=p[i+1][j];
p[i][a[i]]++;
}
long long ans=0;
for(int j=2;j<=n;j++){
for(int k=j+1;k<=n;k++){
ans+=1ll*p[k+1][a[j]]*f[j-1][a[k]];
}
}
cout<<ans<<endl;
}
int main(){
int T=rd();
while(T--) solve();
return 0;
}