大体题意:
街道上住着n 个 人,每个人都喜欢打乒乓球,他们之间会互相切磋,那组织一场乒乓球比赛需要三个人,一个裁判,两个运动员,要求裁判的能力值要介于两个运动员之间,并且位置也在他们之间,问最后有多少种选法?
思路:
输入完n 个数后,统计 在a[i]左边比a[i]小的个数 有sml[i]个,那么大的就有i-1-sml[i]个,在统计右边比a[i]小的个数 smr[i]个,那么大的个数就有n-i-smr[i]个!
最终答案就是遍历裁判即可!裁判从2~n 依次遍历即可!
题目比较简单,具体不说了。
详细见代码
注意 用long long 还有树状数组 x <= 范围尽可能大,莫名的wa!!!
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 100000 + 10;
int a[maxn],sml[maxn],smr[maxn],c[maxn];
int n;
int lowbit(int x){
return x&-x;
}
void add(int x,int d){
while(x <= maxn){
c[x] += d;
x += lowbit(x);
}
}
int sum(int x){
int ans = 0;
while(x > 0){
ans += c[x];
x -= lowbit(x);
}
return ans;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for (int i = 1; i <= n; ++i){
scanf("%d",&a[i]);
}
memset(c,0,sizeof c);
for (int i = 1; i <= n; ++i){
add(a[i],1);
sml[i] = sum(a[i]-1);
}
memset(c,0,sizeof c);
for (int i = n; i >= 1; --i){
add(a[i],1);
smr[i] = sum(a[i]-1);
}
ll ans = 0ll;
for (int i = 2 ; i < n; ++i){
ans += (ll)sml[i]*(ll)(n-i-smr[i]) + (ll)smr[i] * (ll)(i-1-sml[i]);
}
printf("%lld\n",ans);
}
return 0;
}