题目描述:
一个简单的数列问题:给定一个长度为n的数列,求这样的三个元素 a i , a j , a k a_i, a_j, a_k ai,aj,ak的个数,满足 a i < a j > a k a_i < a_j > a_k ai<aj>ak,且 i < j < k i < j < k i<j<k。
输入:
第一行是一个整数 n ( n ≤ 50000 ) n(n \le 50000) n(n≤50000)。
第二行n个整数 a i ( 0 ≤ a i ≤ 32767 ) a_i(0 \le a_i \le 32767) ai(0≤ai≤32767)。
输出:
一个数,满足 a i < a j > a k ( i < j < k ) a_i < a_j > a_k (i < j < k) ai<aj>ak(i<j<k)的个数。
样例输入:
5
1 2 3 4 1
样例输出:
6
实现代码:
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
#define lowbit(i) ((i)&(-i))
const int maxn = 5e4 + 10;
const int maxv = 32769;
int n;
int c[maxv];
int A[maxn];
int low[maxn];
int up[maxn];
void update(int x, int v) {
for(int i = x; i < maxv; i += lowbit(i)) {
c[i] += v;
}
}
int getSum(int x) {
int sum = 0;
for(int i = x; i > 0; i -= lowbit(i)) {
sum += c[i];
}
return sum;
}
int main() {
while(scanf("%d", &n) != EOF) {
memset(c, 0, sizeof(c));
memset(A, 0, sizeof(A));;
long long sum = 0;
for(int i = 0; i < n; i++) {
scanf("%d", &A[i]);
A[i]++;
update(A[i], 1);
low[i] = getSum(A[i] - 1);
}
memset(c, 0, sizeof(c));
for(int i = n - 1; i >= 0; i--) {
update(A[i], 1);
up[i] = getSum(A[i] - 1);
sum += low[i] * up[i];
}
printf("%lld\n", sum);
}
return 0;
}
/*
此题不能用动态规划来求会超时,故采用树状数组,而树状数组无法处理0,因此我们可以采用整体加1的方式,这不会改变结果。
*/