题目大意是给定一串1到n的排列(设为数组a),求其中满足a[x]<a[z]<a[y]的排列个数,其中x<y<z
直接求这样的排列个数并不好求,我们可以转化为求a[x]<a[z]<a[y]+a[x]<a[y]<a[z]的个数减去a[x]<a[z]<a[y]的个数
用left数组记录i位置前比a[i]小的元素个数,left数组可由树状数组预处理得到,那么我们可以得到求排列个数的公式(具体见码)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
using namespace std;
#define LL long long
const LL maxn = 100000 + 5;
LL C[2 * maxn], lef[maxn], n; //lef数组表示i之前比a[i]小的数的个数
LL lowbit(LL x) {
return x&(-x);
}
void add(LL x, LL d){
while(x <= n) {
C[x] += d; x += lowbit(x);
}
}
LL sum(LL x) {
LL ret = 0;
while(x > 0) {
ret += C[x]; x -= lowbit(x);
}
return ret;
}
int main() {
LL t, kase = 0; scanf("%I64d", &t);
while(t--) {
memset(C, 0, sizeof(C));
scanf("%I64d", &n);
LL ans = 0;
for(LL i = 1; i <= n; i++) {
LL tmp;
scanf("%I64d", &tmp);
lef[i] = sum(tmp);
add(tmp, 1);
// prLLf("%I64d\n", lef[i]);
ans = ans + (n + lef[i] + 1 - tmp - i) * (n + lef[i] - tmp - i) / 2 - (n + lef[i] + 1 - tmp - i) * lef[i];
}
printf("Case #%I64d: %I64d\n", ++kase, ans % 100000007);
}
return 0;
}
原文:http://blog.csdn.net/u014664226/article/details/45827609