ccpc_南阳 C The Battle of chibi dp + 树状数组
题意:给你一个n个数的序列,要求从中找出含m个数的严格递增子序列,求能找出多少种不同的方案
dp[i][j]表示以第i个数结尾,形成的严格递增子序列长度为j的方案数
那么最终的答案应该就是sigma(dp[i][m]);
显然有:dp[i][j] = sigma(dp[k][j - 1]); 其中 1 <= k < i 且 a[k] < a[i];
题目要求严格递增,这个限制怎么解决?
hdu4719这道题同样是这样处理,即我们只需要从小到大dp就行了。
但是复杂度是O(n^3)的,显然需要优化,注意到应该从小到大dp之后,我们要做的就是快速求出sigma(dp[k][j-1]) (还未计算到的dp值为0) (注意不能直接用数组维护前缀和)
可以用树状数组得到优化,最终复杂度是O(n^2logn)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | #include <bits/stdc++.h> #define lowbit(x) (x) & (-x) using namespace std; const int N = 1005; const int M = 1e9 + 7; int dp[N][N], c[N][N]; int a[N], r[N]; bool cmp( int b, int c) { return a[b] < a[c]; } void update( int i, int j, int value) { while (i < N) { c[i][j] = c[i][j] + value % M; i += lowbit(i); } } int sum( int i, int j) { int s = 0; while (i > 0) { s = s + c[i][j] % M; i -= lowbit(i); } return s % M; } int main() { int n, m; int _, cas = 1; scanf ( "%d" , &_); while (_ --) { scanf ( "%d%d" , &n, &m); for ( int i = 1; i <= n; ++i) scanf ( "%d" , &a[i]); memset (c, 0, sizeof c); memset (dp, 0, sizeof dp); for ( int i = 0; i <= n; ++i) r[i] = i; sort(r + 1, r + n + 1, cmp); for ( int i = 1; i <= n; ++i) { int id = r[i]; dp[id][1] = 1; update(id, 1, 1); for ( int j = 2; j <= m; ++j) { dp[id][j] = sum(id - 1, j - 1); update(id, j, dp[id][j]); } } int ans = 0; for ( int i = 1; i <= n; ++i) ans = ans + dp[i][m] % M; printf ( "Case #%d: %d\n" , cas++, ans % M); } return 0; } |
分类:
竞赛
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧