您的位置:首页 > 其它

hdu 2492 Ping pong 树状数组 求逆序数

2015-07-23 09:15 381 查看
原题链接:点击打开链接

题意:有t组数据,每行数据的第一个数 n 表示有n个人,每个位置上的数据代表选手的技能值,现在要三个人组队,按照位置的顺序,三个人中间的人是裁判,两边的选手,裁判的技能值要跟位置一样位于两位选手之间。

思路:一个点一个点的判断,求该点点左边比它大的数的个数,右边比它小的数的个数,相乘就是一部分的解,再求左边比它小的数的个数,右边比它大的数的个数,相乘得另一部分的解,两部分的解相加就是要求的结果 。

code:

#include<stdio.h>
#include<string.h>
#define MAX 100100
int n,c[MAX],l1[MAX],l2[MAX],r1[MAX],r2[MAX],a[MAX];
int flag;

int Lowbit(int k)
{return (k&-k);}

void update(int pos,int num)
{
	while(pos<MAX)//是MAX 而不是 n
    {
		c[pos]+=num;
		pos+=Lowbit(pos);
	}
}
int sum(int pos)
{
	int s=0;
	while(pos>0)
	{
		s+=c[pos];
		pos-=Lowbit(pos);
	}
	return s;
}
int main()
{
   // freopen("i.txt","r",stdin);
       int i,t;
	   scanf("%d",&t);
	   while(t--)
	   {
		   memset(c,0,sizeof(c));
		   scanf("%d",&n);
		   for(i=1;i<=n;i++)//求左边比该点技能值大的数的个数,小的数的个数
		   {
			   scanf("%d",&a[i]);
			   l1[i]=sum(a[i]); //输入的i个数中 有 sum(a[i]) 个比a[i]小
			   l2[i]=i-1-l1[i]; //输入的i个数中 有 i-1-sum(a[i]) 个比a[i]大
			   update(a[i],1);
		   }
		   memset(c,0,sizeof(c));
		   int j=1;//代表现在输入的数的个数
		   for(i=n;i>=1;i--,j++)//求右边比该点技能值大的数的个数,小的数的个数
		   {
				 r1[i]=sum(a[i]);//输入a[i]后 输入的那些数中有 sum(a[i]) 个比a[i]小的
				 r2[i]=j-1-r1[i]; //输入a[i]后输入的那些数中有 j-1-sum(a[i] 个比a[i]大的
				 update(a[i],1);
		   }
		   __int64 ans=0;
		   for(i=1;i<=n;i++)
			  ans+=l1[i]*r2[i]+l2[i]*r1[i];
		   printf("%I64d\n",ans);
	   }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: