POJ 3928 & HDU 2492 Ping pong(树状数组求逆序数)
题目链接:
PKU:http://poj.org/problem?id=3928
HDU:http://acm.hdu.edu.cn/showproblem.php?pid=2492
Description
Input
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
Sample Input
1 3 1 2 3
Sample Output
1
Source
代码如下:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn=100017; int n; int a[maxn], c[maxn]; int leftMax[maxn], leftMin[maxn]; int rightMax[maxn], rightMin[maxn]; typedef __int64 LL; int Lowbit(int x) //2^k { return x&(-x); } void update(int i, int x)//i点增量为x { while(i <= maxn)//注意此处 { c[i] += x; i += Lowbit(i); } } int sum(int x)//区间求和 [1,x] { int sum=0; while(x>0) { sum+=c[x]; x-=Lowbit(x); } return sum; } int main() { int t; int n; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i = 1; i <= n; i++) { scanf("%d",&a[i]); } memset(c,0,sizeof(c)); for(int i = 1; i <= n; i++) { leftMin[i] = sum(a[i]);//计算左边小的个数 leftMax[i] = i-leftMin[i]-1;//计算左边大的个数 update(a[i],1); } memset(c,0,sizeof(c));//再次清零 for(int i = n,j = 1; i >= 1; i--,j++) { rightMin[i] = sum(a[i]); rightMax[i] = j-rightMin[i]-1; update(a[i],1); } LL ans = 0; for(int i = 1; i <= n; i++) { ans+=leftMax[i]*rightMin[i] + leftMin[i]*rightMax[i];//交叉相乘取和 } printf("%I64d\n",ans); } return 0; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。