题目:
大致翻译:
给一个数组 P P P,其中 a < b < c < d a<b<c<d a<b<c<d,求满足 P a < P c Pa<Pc Pa<Pc & P b > P d Pb>Pd Pb>Pd 的四元组数目。
思路:
枚
举
P
b
,
P
a
随
之
更
新
,
将
P
a
放
入
数
组
中
,
求
其
前
缀
和
。
枚举Pb,Pa随之更新,将Pa放入数组中,求其前缀和。
枚举Pb,Pa随之更新,将Pa放入数组中,求其前缀和。
作
用
:
借
助
前
缀
和
标
记
小
于
等
于
P
a
的
个
数
,
即
d
[
j
]
:
此
时
已
经
出
现
过
的
a
[
i
−
1
]
中
小
于
等
于
j
的
个
数
。
作用:借助前缀和标记小于等于Pa的个数,即d[j]:此时已经出现过的a[i-1]中小于等于j的个数。
作用:借助前缀和标记小于等于Pa的个数,即d[j]:此时已经出现过的a[i−1]中小于等于j的个数。
然
后
枚
举
P
d
,
P
b
>
P
d
时
更
新
答
案
,
在
此
之
后
更
新
P
a
<
P
c
的
数
目
(
因
为
随
着
P
d
往
后
P
c
可
选
范
围
增
加
,
所
以
P
a
<
P
c
的
数
目
可
能
增
加
)
然后枚举Pd,Pb>Pd时更新答案,在此之后更新Pa < Pc 的数目(因为随着Pd往后Pc可选范围增加,所以Pa<Pc的数目可能增加)
然后枚举Pd,Pb>Pd时更新答案,在此之后更新Pa<Pc的数目(因为随着Pd往后Pc可选范围增加,所以Pa<Pc的数目可能增加)
代码:
#include<bits/stdc++.h>
using namespace std;
//#define ll long long
#define int long long
const int N = 5e3+10;
int d[N],a[N],tong[N];
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int t;cin>>t;
int n;
while(t--){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];tong[i]=0;
}
int ans=0,res;
for(int i=2;i<n;i++){//枚举b(i)
tong[a[i-1]]++;//每次将a(i-1)放入
// 借助前缀和标记小于等于a的个数,即d[j]:此时已经出现过的a[i-1]中小于等于j的个数
for(int j=1;j<=n;j++)d[j]=d[j-1]+tong[j];
// for(int j=1;j<=n;j++)cout<<d[j]<<" ";cout<<endl;
res=d[a[i+1]];//c(i),此时a<c的数目
for(int j=i+2;j<=n;j++){//枚举d(j)
if(a[i]>a[j])ans+=res;//b(i-1)>d(j)
res+=d[a[j]]; //更新此时a<c的数目 c(j)
// cout<<"res="<<res<<" ans="<<ans<<endl;
}
}
cout<<ans<<endl;
}
return 0;
}