预处理,暴力枚举,巧妙地转换枚举对象,前缀和,状态表示
对于此题,定义一个辅助数组则很好求解
sum[i]][j],将b放置在第i个位置上,可选前j个数字的可选方案数
反之,可得到c的sum状态表示
由于a<b<c<d,可观察出,sumb与sumc可合并为同一个sum数组,详见代码
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int N = 5005;
int a[N];
int n;
int sum[N][N];
int main()
{
int _; cin >> _;
while (_--)
{
cin >> n;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
sum[i][j] = 0;
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
int cnt;
for (int i = 0; i < n; i++)
{
cnt = 0;
for (int j = 0; j < i; j++)
{
if (a[j] < a[i])cnt++;
sum[i][j] = cnt;
}
cnt = 0;
for (int j = n - 1; j > i; j--)
{
if (a[j] < a[i])cnt++;
sum[i][j] = cnt;
}
}
ll ans = 0;
for(int b = 1; b < n - 2; b++)
for (int c = b + 1; c < n - 1; c++)
{
ans += 1ll*sum[b][c + 1] * sum[c][b - 1];
}
printf("%lld\n", ans);
}
return 0;
}