b_hdu_Ping pong(树状数组+乘法原理)
有n个人要进行乒乓球比赛每一个人都一个能力值;现在要求进行一场1个裁判2个选手的比赛,不能选择技术等级高于或低于他们两人的裁判,裁判位置也需在两人的中间,问一共可以进行这种比赛多少次。(1<=ai<=100000, N<20000)
1
3 1 2 3
1
思路
树状数组+乘法原理
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
ll n, ans, a[N], c[N], lmin[N], rmax[N], lmax[N], rmin[N];
int lowbit(int x) {return x&-x;}
void add(int x, ll v) {
for (; x<N; x+=lowbit(x)) c[x]+=v;
}
ll ask(int x) {
ll ans=0;
for (; x>0; x-=lowbit(x)) ans+=c[x];
return ans;
}
int main() {
std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int t; cin>>t;
while (t--) {
memset(c,0,sizeof c);
cin>>n; for (int i=1; i<=n; i++) cin>>a[i], lmin[i]=lmax[i]=rmin[i]=rmax[i]=0;
for (int i=1; i<=n; i++) {
ll l=ask(a[i]);
lmin[i]=l, lmax[i]=i-l-1;
add(a[i], 1);
}
memset(c,0,sizeof c);
for (int i=n,j=1; i>0; i--,j++) {
ll r=ask(a[i]); //右边比a[i].v小的数的个数
rmin[i]=r, rmax[i]=j-r-1;
add(a[i], 1);
}
// for (int i=1; i<=n; i++) cout<<lmin[i];
// cout<<'\n';
// for (int i=1; i<=n; i++) cout<<lmax[i];
// cout<<'\n';
// for (int i=1; i<=n; i++) cout<<rmin[i];
// cout<<'\n';
// for (int i=1; i<=n; i++) cout<<rmax[i];
for (int i=1; i<=n; i++) ans+=lmin[i]*rmax[i]+lmax[i]*rmin[i];
cout<<ans<<'\n';
}
return 0;
}