标签:
对应HDU题目:点击打开链接
思路:举个例子(等级不一定是1~N)
1 3 7 6 9 8 5
如果6是裁判,那左边等级比他低的人数(顺序数)a= 2;右边等级比他高的人数(顺序数)b = 2;左边等级比他高的人数(逆序数)c= 1;右边等级比他低的人数(逆序数)d = 1;
所以6做裁判的话就能组成a*b + c*d = 5个不同的比赛。
从左到右for一遍,把每个人做裁判能组成的比赛数目加起来就是结果。
逆序数与顺序数的求解可用树状数组
具体实现代码:
#include<cstdio> #include<cstdlib> #include<cmath> #include<map> #include<queue> #include<stack> #include<vector> #include<algorithm> #include<cstring> #include<string> #include<iostream> const int MAXN=20000+10; using namespace std; int a[MAXN]; int highl[MAXN];//highl[i]表示第i个数左边比a[i]大的数的个数 int highr[MAXN];//highr[i]表示第i个数右边比a[i]大的数的个数 int lowl[MAXN];//lowl[i]表示第i个数左边比a[i]小的数的个数 int lowr[MAXN];//lowr[i]表示第i个数右边比a[i]小的数的个数 int c[MAXN*5]; int lowbit(int x) { return x&(-x); } void update(int x, int num) { while(x <= 5*MAXN-2) { c[x] += num; x += lowbit(x); } } int sum(int x) { int res = 0; while(x > 0) { res += c[x]; x -= lowbit(x); } return res; } int main() { //freopen("in.txt","r",stdin); int T; scanf("%d", &T); while(T--) { int n; memset(c,0,sizeof(c)); scanf("%d", &n); for(int i=0; i<n; i++){ scanf("%d", a+i); int x = a[i]; highl[i] = sum(5*MAXN) - sum(x); lowl[i] = sum(x); update(x,1); } memset(c,0,sizeof(c)); for(int i=n-1; i>=0; i--){ int x = a[i]; highr[i] = sum(5*MAXN) - sum(x); lowr[i] = sum(x); update(x,1); } long long Sum = 0; for(int i=0; i<n; i++){//乘法原理和加法原理 Sum += (long long) highl[i] * lowr[i]; Sum += (long long) lowl[i] * highr[i]; } printf("%lld\n", Sum); } return 0; }
标签:
原文地址:http://blog.csdn.net/u013351484/article/details/42102271