您的位置:首页 > Web前端

Uva 1428 Ping pong (树状数组,Fenwick树)

2014-08-14 08:49 471 查看
N(3

N

20000) ping
pong players live along a west-east street(consider the street as a line segment). Each player has a unique skill rank. To improve their skill rank, they often compete with each other. If two players want to compete, they must choose a referee among other
ping pong players and hold the game in the referee's house. For some reason, the contestants can't choose a referee whose skill rank is higher or lower than both of theirs. The contestants have to walk to the referee's house, and because they are lazy, they
want to make their total walking distance no more than the distance between their houses. Of course all players live in different houses and the position of their houses are all different. If the referee or any of the two contestants is different, we call
two games different. Now is the problem: how many different games can be held in this ping pong street?


Input

The first line of the input contains an integer T(1

T

20) ,
indicating the number of test cases, followed by T lines each of which describes a test case.

Every test case consists of N + 1 integers. The first integer is N , the number of players. Then N distinct integers a1, a2...aN follow,
indicating the skill rank of each player, in the order of west to east ( 1

ai

100000 , i =
1...N ).


Output

For each test case, output a single line contains an integer, the total number of different games.


Sample Input

1
3 1 2 3



Sample Output

1


题意:N个乒乓运动员住在一条街上,他们经常组织比赛切磋,每个运动员有一个能力值。每场比赛需要三个人,裁判和两个运动员,规则是裁判必须住在两个运动员中间而且能力值也必须在他们之间。问共能组织多少场比赛。

分析:题目意思很明确,对于每个裁判i,只要求出前面比ai小的数和后面比ai大的数相乘,加上后面比ai小的数加上前面比ai大的数。公式就是 c[i]*(n-i-d[i])+(i-1-c[i])*d[i],c[i]和d[i]分别表示i前后比i小的数的个数。
要求出c[i]和d[i]就要用到Fenwick树(其实就是树状数组),很典型的求逆序数方法,正反求两遍即可,复杂度O(nlogr),r指的是ai的最大值。

AC代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 100005;
int fwt[maxn],c[maxn],d[maxn],a[maxn];
int n,mxn;
inline int lowbit(int x){return x&(-x);}

void add(int x,int cg){
while(x<=mxn){
fwt[x]+=cg;
x+=lowbit(x);
}
}
int query(int x){
int ans =0;
while(x>0){
ans+=fwt[x];
x-=lowbit(x);
}
return ans;
}
int main()
{
int T;
cin>>T;
while(T--){
scanf("%d",&n);
mxn = -1;
long long ans = 0;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),mxn = max(a[i],mxn);
memset(fwt,0,sizeof(fwt));
for(int i=1;i<=n;i++){
add(a[i],1);
c[i] = query(a[i]-1);
}
memset(fwt,0,sizeof(fwt));
for(int i=n;i>=1;i--){
add(a[i],1);
d[i] = query(a[i]-1);
}
for(int i=1;i<=n;i++){
ans+=(long long)c[i]*(n-i-d[i])+(long long)(i-1-c[i])*d[i];
}
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: