您的位置:首页 > 产品设计 > UI/UE

uestc oj 1217 The Battle of Chibi (dp + 离散化 + 树状数组)

2016-09-23 18:47 351 查看
题目链接:http://acm.uestc.edu.cn/#/problem/show/1217

给你一个长为n的数组,问你有多少个长度严格为m的上升子序列。

dp[i][j]表示以a[i]结尾长为j的上升子序列个数。常规是三个for。

这里用树状数组优化一下,类似前缀和的处理,两个for就好了。

//#pragma comment(linker, "/STACK:102400000, 102400000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
using namespace std;
typedef long long LL;
typedef pair <int, int> P;
const int N = 1e3 + 5;
LL dp

, mod = 1e9 + 7;
int a
, b
, m, n;
LL bit

;

void add(int pos, int i, int val) { //上升子序列长度为pos
for( ; i <= n; i += (i&-i))
bit[pos][i] = (bit[pos][i] + val) % mod;
}

LL sum(int pos, int i) {
LL s = 0;
for( ; i >= 1; i -= (i&-i))
s = (s + bit[pos][i]) % mod;
return s;
}

int main()
{
int t;
scanf("%d", &t);
for(int ca = 1; ca <= t; ++ca) {
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; ++i) {
scanf("%d", a + i);
b[i] = a[i];
}
sort(b + 1, b + n + 1);
for(int i = 1; i <= n; ++i) {
a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b; //离散化
}
memset(dp, 0, sizeof(dp));
memset(bit, 0, sizeof(bit));
dp[1][1] = 1;
add(1, a[1], 1);
for(int i = 2; i <= n; ++i) {
dp[i][1] = 1;
for(int k = max(m - (n - i), 1); k <= min(i, m); ++k) { //这边可以优化一下
dp[i][k] = (dp[i][k] + sum(k - 1, a[i] - 1)) % mod; //比a[i]小且上升子序列长度为k-1
add(k, a[i], dp[i][k]);
}
}
LL res = 0;
for(int i = 1; i <= n; ++i) {
res = (res + dp[i][m]) % mod;
}
printf("Case #%d: %lld\n", ca, res);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: