题意:
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5792
对于给出的数组A,求有多少个四元组< a,b,c,d >,满足a < b,c < d且A[a] < A[b]&&A[c] > A[d],其中a,b,c,d要两两不同。
思路:
离散化,然后树状数组统计正序对和逆序对,相乘的总和减掉其中有重复的即可。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 5e4 + 10;
int a[MAXN];
struct BIT {
int n;
int C[MAXN];
void init(int n) {
this->n = n;
memset(C, 0, sizeof(C));
}
int lowbit(int x) {
return x & -x;
}
void add(int x, int y) {
while (x <= n) {
C[x] += y;
x += lowbit(x);
}
}
int sum(int x) {
int res = 0;
while (x) {
res += C[x];
x -= lowbit(x);
}
return res;
}
} bit;
int discre(int n) {
vector <int> vec;
for (int i = 1; i <= n; i++) {
vec.push_back(a[i]);
}
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(), vec.end()), vec.end());
int m = 0;
for (int i = 1; i <= n; i++) {
a[i] = lower_bound(vec.begin(), vec.end(), a[i]) - vec.begin() + 1;
m = max(m, a[i]);
}
return m;
}
int l1[MAXN], r1[MAXN], l2[MAXN], r2[MAXN];
int main() {
//freopen("in.txt", "r", stdin);
int n;
while (scanf("%d", &n) != EOF) {
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
int m = discre(n);
LL cnt1 = 0, cnt2 = 0;
bit.init(m);
for (int i = 1; i <= n; i++) {
l1[i] = bit.sum(a[i] - 1);
bit.add(a[i], 1);
cnt1 += l1[i];
}
bit.init(m);
for (int i = 1; i <= n; i++) {
l2[i] = bit.sum(m) - bit.sum(a[i]);
bit.add(a[i], 1);
}
bit.init(m);
for (int i = n; i >= 1; i--) {
r1[i] = bit.sum(a[i] - 1);
bit.add(a[i], 1);
cnt2 += r1[i];
}
bit.init(m);
for (int i = n; i >= 1; i--) {
r2[i] = bit.sum(m) - bit.sum(a[i]);
bit.add(a[i], 1);
}
LL ans = (LL)cnt1 * cnt2;
for (int i = 1; i <= n; i++) {
ans -= (LL)l1[i] * r1[i];
ans -= (LL)l1[i] * l2[i];
ans -= (LL)l2[i] * r2[i];
ans -= (LL)r1[i] * r2[i];
}
printf("%I64d\n", ans);
}
return 0;
}