NOI模拟赛(3.15) sequence(序列)
Solution
题目有一个隐藏性质是这样的
答案的第一问是对于每个点为结束点或开始点求出的最长上升序列长度和最长下降序列长度之和
在dp以上两个值的过程中同时统计方案数,用树状数组可以n log n时间复杂度做到
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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | #include <vector> #include <stdio.h> #include <string.h> #include <algorithm> #define set_file(File) freopen(#File".in", "r", stdin), freopen(#File".out", "w", stdout) #define close_file() fclose(stdin), fclose(stdout) #define ll long long #define mo 1000000007 #define maxn 200010 template < class T> inline void Rin(T &x) { int c = getchar (); for (x = 0; c < 48 || c > 57; c = getchar ()); for (; c > 47 && c < 58; c = getchar ()) x = (x << 1) + (x << 3) + c - 48; } std::vector< int > VeH; int n, seq[maxn], mx[maxn], c[maxn], f[maxn], fs[maxn], g[maxn], gs[maxn]; void get_ans_lef( int i) { int x = seq[i] - 1, tot = 1, ans = 0; for (; x; x -= x & -x) { if (mx[x] > ans) ans = mx[x], tot = c[x]; else if (mx[x] == ans) tot = (tot + c[x]) % mo; } f[i] = ans + 1, fs[i] = tot; x = seq[i]; for (; x <= n; x += x & -x) { if (mx[x] < f[i]) mx[x] = f[i], c[x] = fs[i]; else if (mx[x] == f[i]) c[x] = (c[x] + fs[i]) % mo; } } void get_ans_rig( int i) { int x = seq[i] - 1, tot = 1, ans = 0; for (; x; x -= x & -x) { if (mx[x] > ans) ans = mx[x], tot = c[x]; else if (mx[x] == ans) tot = (tot + c[x]) % mo; } g[i] = ans + 1, gs[i] = tot; x = seq[i]; for (; x <= n; x += x & -x) { if (mx[x] < g[i]) mx[x] = g[i], c[x] = gs[i]; else if (mx[x] == g[i]) c[x] = (c[x] + gs[i]) % mo; } } int main() { set_file(sequence); Rin(n); for ( int i = n; i; i--) { Rin(seq[i]); VeH.push_back(seq[i]); } std::sort(VeH.begin(), VeH.end()); VeH.erase(unique(VeH.begin(), VeH.end()), VeH.end()); for ( int i = 1; i <= n; i++) seq[i] = std::lower_bound(VeH.begin(), VeH.end(), seq[i]) - VeH.begin() + 1; for ( int i = 1; i <= n; i++) get_ans_lef(i); memset (mx, 0, sizeof mx); memset (c, 0, sizeof c); for ( int i = 1; i <= n; i++) seq[i] = n - seq[i] + 1; for ( int i = 1; i <= n; i++) get_ans_rig(i); int tot = 0, ans = 0; for ( int i = 1; i <= n; i++) if (f[i] + g[i] - 1 > ans) ans = f[i] + g[i] - 1, tot = (ll)fs[i] * gs[i] % mo; else if (f[i] + g[i] - 1 == ans) tot = (tot + (ll)fs[i] * gs[i] % mo) % mo; for ( int i = 1; i <= n - ans; i++) tot = (ll)tot * 2 % mo; printf ( "%d %d\n" , ans, tot); close_file(); return 0; } |
分类:
基础算法---动态规划
, 数据结构---树状数组
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)