UVA1428 Ping pong(树状数组)
思路:权值树状数组。
考虑枚举每个位置作为裁判对答案的贡献。
显然有两种情况:
因为每个数互异。
根据乘法原理所以贡献为:
且题目数据 .所以可以用权值树状数组来维护。
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=2e4+5,M=1e5+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
int t,n,a[N],tr[M];
int l_up[N],l_low[N],r_up[N],r_low[N];
#define lowbit(x) x&(-x)
void update(int x,int k){
while(x<=1e5){
tr[x]+=k;
x+=lowbit(x);
}
}
ll query(int x){
ll ans=0;
while(x){
ans+=tr[x];
x-=lowbit(x);
}
return ans;
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
l_up[i]=query(a[i]);
l_low[i]=i-l_up[i]-1;
update(a[i],1);
}
for(int i=1;i<=1e5;i++)
tr[i]=0;
ll ans=0;
for(int i=n;i>=1;i--){
r_up[i]=query(a[i]);
r_low[i]=n-i-r_up[i];
ans+=1LL*l_up[i]*r_low[i];
ans+=1LL*l_low[i]*r_up[i];
update(a[i],1);
}
for(int i=1;i<=1e5;i++)
tr[i]=0;
printf("%lld\n",ans);
}
return 0;
}