题目:
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=13895
题意:一条街上住有n个乒乓选手,他们有一个技能值,现在每场比赛要3个人,两个选手,一个裁判;裁判须住在他们之间,且其技能值必须在两选手之间,求一其能组织多少种比赛。
思路:首先,每个人能组织的比赛数量为 其左边技能比他小的人的数量*右边比他大的 +左边比他大的*右边比他小的。这个容易想到。
这题有点像 hdu 的 1394 题解
题意:一条街上住有n个乒乓选手,他们有一个技能值,现在每场比赛要3个人,两个选手,一个裁判;裁判须住在他们之间,且其技能值必须在两选手之间,求一其能组织多少种比赛。
思路:首先,每个人能组织的比赛数量为 其左边技能比他小的人的数量*右边比他大的 +左边比他大的*右边比他小的。这个容易想到。
这题有点像 hdu 的 1394 题解
建两个数组 lmin 和 rmin 分别表示选手i左边比他小的数量和右边比他小的数量。用线段树求解,结点cnt值表示在该段中插入值出现的次数,算lmin时,从左到右依次插入每个选手的val值,此时只更新线段树,然后查询0~val[i]-1,这区间有多少个数出现过,就是lmin的值(想不清楚的画个图看一下)。同理,求rmin是从右到左依次插入val[i]。
//0 KB 539 ms
#include <stdio.h>
#include <string.h>
#define LL long long
#define L(u) (u<<1)
#define R(u) (u<<1|1)
const int M = 20005;
const int N = 100005;
struct Node
{
int l,r;
int cnt;
} node[N<<2];
int lmin[M],rmin[M],val[M];
int min (int a,int b)
{
return a > b ? b : a;
}
int max (int a,int b)
{
return a > b ? a : b ;
}
void Build (int u,int left,int right)
{
node[u].l = left,node[u].r = right;
node[u].cnt = 0;
if (node[u].l == node[u].r)
return ;
int mid = (node[u].l + node[u].r)>>1;
Build (L(u),left,mid);
Build (R(u),mid+1,right);
}
void Update (int u,int key)
{
if (node[u].l == node[u].r)
{
node[u].cnt ++;
return ;
}
int mid = (node[u].l + node[u].r)>>1;
if (key <= mid) Update(L(u),key);
else Update(R(u),key);
node[u].cnt = node[L(u)].cnt + node[R(u)].cnt;
}
int Query(int u,int left,int right)
{
if (left <= node[u].l &&node[u].r <= right)
return node[u].cnt;
int mid = (node[u].l + node[u].r)>>1;
if (right <= mid) return Query(L(u),left,right);
else if (left > mid) return Query(R(u),left,right);
else return (Query(L(u),left,mid) + Query(R(u),mid+1,right));
}
int main ()
{
int T,n,i;
scanf ("%d",&T);
while (T --)
{
scanf ("%d",&n);
int m = 0;
for (i = 1; i <= n; i ++)
{
scanf ("%d",&val[i]);
m = max(m,val[i]);
}
Build (1,0,m);
for (i = 1;i <= n;i ++)
{
Update(1,val[i]);
lmin[i] = Query(1,0,val[i]-1);
}
Build (1,0,m);
for (i = n;i >= 1;i --)
{
Update(1,val[i]);
rmin[i] = Query(1,0,val[i]-1);
}
//for (i = 1;i <= n;i ++)
// printf ("%d %d\n",lmin[i],rmin[i]);
LL ans = 0;
for (i = 1; i <= n; i ++)
ans += lmin[i]*(n-i-rmin[i]) + (i-1-lmin[i])*rmin[i];
printf ("%lld\n",ans);
}
return 0;
}