题目链接:http://poj.org/problem?id=3378
题目大意:
找出原序列中满足:
1. 1 ≤ i < j < k < l < m ≤ N
2. Ai < Aj < Ak < Al < Am
两个条件长度为5的子序列个数。
题目分析:
长度为5,我们可以从长度为1开始推算,一直推到长度为5。
首先,对于长度为1的,所有的数都满足条件。对于长度为2的,我们就可以这样算了:在ai出现之前,有多少个小于ai的数,就有多少以ai结束且长度为2的序列满足条件。同理,对于长度为3的,可以求出在ai之前满足(长度为2且ak<ai)条件的有多少,便可知以ai结尾的长度为3的有多少个;以此类推……
在求ai之前小于ai的数时,可以用数状数组来优化。具体过程是:在求dp[i][j]时,dp[i][j] = sum(dp[i-1][k]); (1<=k<j && ak < ai),即在求和时用树状数组,在求完dp[i][j]后更新树状数组:update(aj, dp[i-1][j]),因为在dp[i][j]里记录的就是长度为i以j结束的序列有多少个。
最后需要注意就是要用高精度了。
代码实现:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define maxn 50005
#define M 100000000
typedef struct{
int a, b, c;
}bint;
int a[maxn], h[maxn], n, len;
bint dp[6][maxn], c[maxn];
int cmp(const void* x, const void* y) {
return *(int*)x - *(int*)y;
}
inline int bs(int v) {
int* p = (int*)bsearch(&v, h + 1, len + 1, sizeof(int), cmp);
return p - h;
}
inline bint add(bint a, bint b) {
a.a += b.a; a.b += b.b; a.c += b.c;
a.b += a.c / M; a.a += a.b / M;
a.b %= M; a.c %= M;
return a;
}
inline void print(bint a) {
if (a.a) {
printf("%d%08d%08d\n", a.a, a.b, a.c);
} else if (a.b) {
printf("%d%08d\n", a.b, a.c);
} else {
printf("%d\n", a.c);
}
}
// 更新树状数组
inline void update(int t, bint v) {
while (t <= n) {
c[t] = add(c[t], v);
t += t & -t;
}
}
// 树状数组求和
inline bint sum(int t) {
bint s = {0, 0, 0};
while (t) {
s = add(s, c[t]);
t -= t & -t;
}
return s;
}
int main() {
while (scanf("%d", &n) != EOF) {
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
h[i] = a[i];
}
// 离散化
qsort(h + 1, n, sizeof(int), cmp);
len = 1;
for (int i = 2; i <= n; i++)
if (h[i] != h[len])
h[++len] = h[i];
for (int i = 1; i <= n; i++)
a[i] = bs(a[i]);
// 对dp[1][i]进行初始化
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++)
dp[1][i].c = 1;
for (int i = 2; i <= 5; i++) {
// 对树状数组c复用,每次归0
memset(c, 0, sizeof(c));
for (int j = i - 1; j <= n; j++) {
dp[i][j] = sum(a[j] - 1); // 先求出dp[i][j]
update(a[j], dp[i - 1][j]); // 再更新c
}
}
// dp[5][]里的结果之和就是最后结果
bint res = {0, 0, 0};
for (int i = 5; i <= n; i++)
res = add(res, dp[5][i]);
print(res);
}
return 0;
}