题目链接:HDU 2492
题意:在一条街上,每个人都有一个不同的武力值,两个人可以相互对决,但是对决必须得满足一个条件,那就是要找个裁判, 裁判的武力值只能介于两者之间,而且两个人对决地点只能在裁判家里,裁判的家必须位于两者之间。
题解:考虑每个做裁判的人可以主持的对决场数,我们按坐标从左至右枚举每个人,这个人可以主持的对决数为(左边武力值比他小的人数)*(右边武力值比他大的人数)+(左边武力值比他大的人数)*(右边武力值比他小的人数)。树状数组维护区间个数即可。
有点类似多校赛的那道题HDU 5792 World is Exploding
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
const int MAX=20000+5;
typedef long long LL;
int a[MAX];
int N=100000;
int bit[100005];
int rs[MAX],rg[MAX],ls[MAX],lg[MAX];
int sum(int x)
{
int s=0;
while(x>0)
{
s+=bit[x];
x-=(x&(-x));
}
return s;
}
void add(int x,int v)
{
while(x<=N)
{
bit[x]+=v;
x+=(x&(-x));
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
memset(bit,0,sizeof(bit));
for(int i=0;i<n;i++)
{
ls[i]=sum(a[i]-1);
//lg[i]=i-ls[i];
lg[i]=sum(N)-sum(a[i]);
add(a[i],1);
}
memset(bit,0,sizeof(bit));
for(int i=n-1;i>=0;i--)
{
rs[i]=sum(a[i]-1);
//rg[i]=i-rs[i];
rg[i]=sum(N)-sum(a[i]);
add(a[i],1);
}
LL ans=0;
for(int i=1;i<n-1;i++)
{
ans=ans+ls[i]*rg[i];
ans=ans+lg[i]*rs[i];
}
printf("%I64d\n",ans);
}
return 0;
}