您的位置:首页 > 其它

HDU - 5792 树状数组 + 离散化

2017-04-26 15:10 381 查看

题意:

题目链接: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: