当前位置: 首页 > news >正文

CF2144E1 思路分享(dp)

https://codeforces.com/problemset/problem/2144/E1

题意概述

\(n\) 座塔从左到右排列,高度为 \(a_i\),记 \(L(a)\) 为从左看依次能看见的塔的高度,\(R(a)\) 为从右看依次能看见的塔的高度,求满足 \(L(a)=L(a')\)\(R(a)=R(a')\)\(a'\) 数量,其中 \(a'\)\(a\) 的子序列,模 \(998244353\).

\(1\le n \le 5000\).

思路

只考虑左边,考虑 \(dp\),记 \(dp1[i][j]\)\(a\) 中前 \(i\) 个元素能匹配 \(L(a)\) 的前 \(j\) 个元素的方案数,讨论每个位置选或不选转移即可.

类似地处理右边,记为 \(dp2\).

考虑如何整合,发现只需关注最大值位置,枚举左边最大值第一次出现位置 \(p\) 和右边最大值第一次出现位置 \(q\),将两边方案数相乘,中间数任选.

为了刻画最大值第一次出现,需要一些处理,记 \(len=|idx|\)\(m_1=|L(a)|\)\(m_2=|R(a)|\), 具体地,总贡献为:

\[\sum_{i=0}^{len}{\sum_{j=i}^{len}{dp1[idx[i]-1][m_1-1] \cdot dp2[idx[j]+1][m_2-1] \cdot 2^{\max(0,idx[j]-idx[i]-1)}}} \]

时间复杂度 \(\mathcal{O}(n^2)\).

代码

//author:kzssCCC#include <bits/stdc++.h>
using namespace std;
using ll = long long;const int MOD = 998244353;
const int INF = 1e9;ll qpow(ll a,ll b){ll res = 1;while (b){if (b&1){res = res*a%MOD;}a = a*a%MOD;b >>= 1;}return res;
}void solve(){int n;cin >> n;vector<int> a(n+1);for (int i=1;i<=n;i++){cin >> a[i];}int pre = 0;vector<int> temp{0};for (int i=1;i<=n;i++){pre = max(pre,a[i]);temp.push_back(pre);}sort(temp.begin()+1,temp.end());temp.erase(unique(temp.begin()+1,temp.end()),temp.end());int m = temp.size()-1;vector<vector<ll>> dp(n+1,vector<ll>(m+1));dp[0][0] = 1;for (int i=1;i<=n;i++){dp[i] = dp[i-1];for (int j=0;j<=m;j++){if (a[i]<=temp[j]){dp[i][j] = (dp[i][j]+dp[i-1][j])%MOD;}else if (j+1<=m && a[i]==temp[j+1]){dp[i][j+1] = (dp[i][j+1]+dp[i-1][j])%MOD;}}} int suf = 0;temp.clear();temp.push_back(0);for (int i=n;i>=1;i--){suf = max(suf,a[i]);temp.push_back(suf);}sort(temp.begin()+1,temp.end());temp.erase(unique(temp.begin()+1,temp.end()),temp.end());int m2 = temp.size()-1;vector<vector<ll>> dp2(n+2,vector<ll>(m2+1));dp2[n+1][0] = 1;for (int i=n;i>=1;i--){dp2[i] = dp2[i+1];for (int j=0;j<=m2;j++){if (a[i]<=temp[j]){dp2[i][j] = (dp2[i][j]+dp2[i+1][j])%MOD;}else if (j+1<=m2 && a[i]==temp[j+1]){dp2[i][j+1] = (dp2[i][j+1]+dp2[i+1][j])%MOD;}}}int mx = temp.back();vector<int> idx;for (int i=1;i<=n;i++){if (a[i]==mx){idx.push_back(i);}}int len = idx.size();ll res = 0;for (int i=0;i<len;i++){for (int j=i;j<len;j++){res = (res+dp[idx[i]-1][m-1]*dp2[idx[j]+1][m2-1]%MOD*qpow(2,max(0,idx[j]-idx[i]-1))%MOD)%MOD;}}cout << res << '\n';
}int main(){ios::sync_with_stdio(false);cin.tie(0);int t = 1;cin >> t;while (t--) solve();return 0;
}
http://www.jsqmd.com/news/1057686/

相关文章:

  • 2026年国内乡村道路太阳能路灯工程工厂,究竟有着怎样的名声?
  • 3分钟掌握Adobe-GenP:终极Adobe软件激活完整指南
  • 2026深圳大型搬家公司实力大盘点:车队规模、人员配置、服务能力三项硬指标评测对比 - 从来都是英雄出少年
  • 一篇讲清亲情账号、家庭共济与医保钱包
  • NJU OS 并发 Bugs 和应对
  • 基于LPC51U68 SCTimer与FreeMASTER的BLDC电机驱动实战指南
  • 融合GNN与LLM的平衡型游戏推荐系统:打破信息茧房
  • 一线观察:长期使用平替科思创 2655 产品的供应商实际体验
  • Ubuntu 14.04下LEMP服务自愈:Monit进程监控与故障自动恢复实战
  • ubbantu24 + sealos 5.1部署k8s + kubesphere
  • Python 操作 SQLite 本地轻量数据库:零配置、无需安装
  • HSTracker:macOS炉石传说玩家的终极智能助手指南 [特殊字符]
  • OpenClaw中文AI本地部署实战:Windows一键运行7B模型
  • V0.2.2发布:修复多行格式输出问题
  • 年度黄金回收数据白皮书出炉,合扬凭硬核实力稳居行业龙头 - 奢侈品交易观察员
  • 逆向工程实战:突破某天气App私有API签名加密,构建高可用Python爬虫系统
  • 7个世代宝可梦游戏终极改造指南:Universal Pokemon Randomizer ZX完全教程
  • MC68HC908AT32存储系统解析:RAM、FLASH与EEPROM实战指南
  • 沈阳黄金回收怎么不被坑?官方白皮书揭秘TOP1合扬靠谱秘诀 - 奢侈品交易观察员
  • 智能水电表防窃电功能实测:那些偷电的花招都不好使了
  • Maestro跨平台UI自动化测试框架:架构解析与实战对比
  • 构建高效后端系统:主流技术栈选型与实践指南
  • 基于Kinetis-M MCU的高精度两相电子电能表设计解析
  • [简化版 GAMES 101] 计算机图形学 14:Blinn-Phong着色模型与着色频率
  • i.MX处理器ATK定制指南:SDRAM初始化、Flash驱动与GUI扩展实战
  • 2026年AI论文工具深度评测:6款工具专业水准得分排名
  • 2026年南京无人机测绘服务商:资质与服务能力客观对比 - 起跑123
  • 一文讲透|2026年最值得体验的专业AI论文写作软件
  • Godot逆向工程:GDScript反编译与资源恢复的完整解决方案
  • 超音速腔体流动中的Rossiter振荡与控制技术