leetcode 133双周赛 统计逆序对的数目「dp」「前缀和优化」

3193. 统计逆序对的数目

题目描述:

给定一个长度为n的二维数组 r e re re,其中 r e [ i ] = [ i d i , c n t i ] re[i] = [id_i, cnt_i] re[i]=[idi,cnti],求存在多少个全排列perm满足对所有的 r e [ i ] re[i] re[i]都有 p e r m [ 0.. i d i ] perm[0..id_i] perm[0..idi]恰好有 c n t i cnt_i cnti个逆序对

答案对1000000007取模

  • 2 <= n <= 300
  • 1 <= requirements.length <= n
  • requirements[i] = [endi, cnti]
  • 0 <= endi <= n - 1
  • 0 <= cnti <= 400
  • 输入保证至少有一个 i 满足 endi == n - 1
  • 输入保证所有的 endi 互不相同。

思路:

首先观察题目类型是求全排列的数量,还要取模,大概率是dp

再看数据范围 n=300,m=400,dp的状态方程完全可以放的下二维的

所以我们考虑用 d p [ i ] [ j ] dp[i][j] dp[i][j]表示满足所有 i d < = i id<=i id<=i的re下,前i个数字 逆序对数量是j 的全排列数量

求解普通逆序对时,我们可以扫一遍数组,对于每个 a r [ i ] ar[i] ar[i],求出 j < i j<i j<i a r [ j ] > a r [ i ] ar[j]>ar[i] ar[j]>ar[i]的数量并求和

在本题,我们也考虑用这种方式来进行状态的转移

对于 i i i,我们只在乎 a r [ i ] ar[i] ar[i] a r [ 1 ] − a r [ i ] ar[1]-ar[i] ar[1]ar[i]中的大小关系,如果 a r [ i ] ar[i] ar[i]在这 i i i个数中排最大,也就是排第 i i i位,则不会产生新的逆序对,即 i − i = 0 i - i = 0 ii=0,如果排最小,也就是排第1位,则会产生 i − 1 i-1 i1个逆序对,如果排第 k k k大,则会产生 i − k i-k ik个新的逆序对

所以,我们可以枚举 a r [ i ] ar[i] ar[i] a r [ 1 ] − a r [ i ] ar[1]-ar[i] ar[1]ar[i]排第几来进行状态转移

对于状态为 d p [ i ] [ j ] dp[i][j] dp[i][j],存在两种情况,一种是i-1层是没有限制的,另一种是i-1层是有固定值限制的

  • 如果 i − 1 i-1 i1处没有题目给定的逆序对数量限制,则枚举k,从0枚举到 m i n ( i , j ) min(i, j) min(i,j) m i n ( i , j ) min(i, j) min(i,j)是因为对于下标从0开始,到 i − 1 i-1 i1的数组,长度为i,此时在末尾添加一个元素,逆序对一次最多只能产生 i i i

    d p [ i ] [ j ] = ∑ k = 0 m i n ( i , j ) d p [ i − 1 ] [ j − k ] dp[i][j] = \sum_{k=0}^{min(i,j)}dp[i-1][j-k] dp[i][j]=k=0min(i,j)dp[i1][jk]

  • 如果 i − 1 i-1 i1处存在题目给定的逆序对数量限制,那只能从那一个状态转移过来,假设r代表则re中对应位置的cnt, 则 d p [ i ] [ j ] = d p [ i − 1 ] [ r ] dp[i][j] = dp[i - 1][r] dp[i][j]=dp[i1][r] r < = j < = r + i r<=j<=r+i r<=j<=r+i

class Solution {const int mod = 1000000007;
public:int numberOfPermutations(int n, vector<vector<int>>& re) {vector<int>p(n, -1);for(auto x : re){p[x[0]] = x[1];}int m = p[n - 1];vector<vector<int>> dp(n, vector<int>(m + 1));dp[0][0] = 1;for(int i = 1; i < n; ++i){if(p[i - 1] == -1){//无限制for(int j = 0; j <= m; ++j){for(int k = 0; k <= min(i, j); ++k){dp[i][j] = (dp[i][j] + dp[i - 1][j - k]) % mod;}}}else{//有限制for(int j = p[i - 1]; j <= min(m, p[i - 1] + i); ++j){dp[i][j] = dp[i - 1][p[i - 1]];}}}return dp[n - 1][p[n - 1]];}
};

也可以用记忆化搜索实现:

class Solution {const int mod = 1000000007;
public:int numberOfPermutations(int n, vector<vector<int>>& re) {vector<int>p(n, -1);p[0] = 0;for(auto x : re){p[x[0]] = x[1];}if(p[0])return 0;int m = p[n - 1];vector<vector<int>> dp(n, vector<int>(m + 1, -1));auto dfs = [&] (auto&& dfs, int i, int j){if(i == 0){return 1;} if(dp[i][j] != -1)return dp[i][j];int & sum = dp[i][j];sum = 0;if(p[i - 1] == -1){for(int k = 0; k <= min(i, j); ++k){sum = (sum + dfs(dfs, i - 1, j - k)) % mod;}}else {if(j >= p[i - 1] && j <= i + p[i - 1]){sum = dfs(dfs, i - 1, p[i - 1]);}}return sum;};return dfs(dfs, n - 1, p[n - 1]);}
};

这样写的时间复杂度是O(n * m * min(n, m)),空间复杂度是O(n * m)

优化

我们可以发现对于无限制的那段 d p [ i ] [ j ] dp[i][j] dp[i][j]是一个连续的区间加法,可以用前缀和来优化枚举k的过程,要注意下标写对了

甚至还可以用滚动数组把空间降下来,这里懒得写了

class Solution {const int mod = 1000000007;
public:int numberOfPermutations(int n, vector<vector<int>>& re) {vector<int>p(n, -1);for(auto x : re){p[x[0]] = x[1];}int m = p[n - 1];vector<vector<int>> dp(n, vector<int>(m + 1, 0));dp[0][0] = 1;for(int i = 1; i < n; ++i){int mx = p[i] == -1 ? m : p[i];if(p[i - 1] == -1){//无限制vector<int>pre(m+1, 0);pre[0] = dp[i - 1][0];for(int j = 1; j <= m; ++j)pre[j] = (pre[j - 1] + dp[i - 1][j])%mod;for(int j = 0; j <= mx; ++j){dp[i][j] = (pre[j] - (j - min(i, j) == 0 ? 0 : pre[j - min(i, j) - 1]) + mod) % mod;}}else{//有限制for(int j = p[i - 1]; j <= min(mx, p[i - 1] + i); ++j){dp[i][j] = dp[i - 1][p[i - 1]];}}}return dp[n - 1][p[n - 1]];}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/37663.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Bayes分类器设计

本篇文章是博主在人工智能等领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对人工智能等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在AI学习笔记&#…

东方博宜 OJ 1201-1300

目录 1268&#xff1a;【基础】高精度加法 1269&#xff1a;【基础】高精度减法 1280&#xff1a;【基础】求 2 的 n 次方 1281&#xff1a;【基础】求 222222⋯222⋯2 1285:【基础】计算 N 的阶乘 1286&#xff1a;【基础】高精度乘单精度 1287&#xff1a;【基础】高精…

第一百三十三节 Java数据类型教程 - Java基本数据类型

Java数据类型教程 - Java基本数据类型 Java定义了八种基本类型的数据:byte&#xff0c;short&#xff0c;int&#xff0c;long&#xff0c;char&#xff0c;float&#xff0c;double和boolean。 基本类型通常被称为简单类型。 这些可以分为四组: Integers - 包括byte&#x…

求推荐几款http可视化调试工具?

Postman 非常流行的API调试工具&#xff0c;适用于构建、测试和文档化APIs。它支持各种HTTP方法&#xff0c;有强大的集合和环境管理功能&#xff0c;以及代码生成能力。 BB-API 是一款旨在提升开发效率的工具&#xff0c;它专注于提供简约、完全免费且功能强大的HTTP模拟请…

目标检测算法

一、绪论 1.1 目标检测算法的定义和背景 1.2 目标检测算法在计算机视觉领域的重要性 二、目标检测算法的发展历程 2.1 传统目标检测算法 2.2 基于深度学习的目标检测算法 2.3 目标检测算法的评价指标 三、目标检测算法的关键技术 3.1 区域建议网络(RPN) 3.2 卷积神经…

springmvc快速上手

一、创建工程 1、创建maven工程&#xff0c;添加maven-archetype-webapp模版 2、添加依赖 <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.co…

每日一题——Python实现PAT乙级1059 C语言竞赛(举一反三+思想解读+逐步优化)四千字好文

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的写法 时间复杂度分析 空间复杂度分析 代码优化建议 总结 我要更强 优化方法…

macos Darwin安装faiss-cpu

文章目录 macos 使用brew instll fass, 后python3.12执行引用faiss包功能出现的问题 安装时遇到问题如下 ModuleNotFoundError Traceback (most recent call last) File ~/Src/ai/framework/langchain/.venv/lib/python3.12/site-packages/langchain_co…

Spring事务的实现

Spring事务的实现分为编程式事务和声明式事务。 编程式事务 编程式事务管理需要开发者在代码中显式地调用事务管理相关的方法,如`beginTransaction()`、`commit()`和`rollback()`等。在Spring中,通常通过以下两种方式来实现编程式事务: 使用`TransactionTemplate`,`Tran…

macOS 安装redis

安装Redis在macOS上通常通过Homebrew进行&#xff0c;Homebrew是macOS上一个流行的包管理器。以下是安装Redis的步骤&#xff1a; 一 使用Homebrew安装Redis 1、安装Homebrew&#xff08;如果尚未安装&#xff09;&#xff1a; 打开终端&#xff08;Terminal&#xff09;并执…

.NET周刊【6月第4期 2024-06-23】

国内文章 C#.Net筑基-集合知识全解 https://www.cnblogs.com/anding/p/18229596 .Net中提供了数组、列表、字典等多种集合类型&#xff0c;分为泛型和非泛型集合。泛型集合具有更好的性能和类型安全性。集合的基础接口包括IEnumerator、IEnumerable、ICollection、IList、ID…

Gradio 4.37.1官方教程二:Blocks

文章目录 一、Blocks及事件监听器1.1 Blocks结构1.2 事件监听器的类型1.3 多数据流1.4 多输入组件1.5 多输出组件1.6 更新组件配置1.7 添加示例1.8 连续运行事件1.9 持续运行事件1.9.1 every参数1.9.2 load方法1.9.3 change方法 1.10 收集事件数据1.11 绑定多个触发器到同一函数…

基于线调频小波变换的一维时间序列时频分析方法(MATLAB)

在机械故障诊断领域,振动信号的处理常采用以快速傅立叶变换为基础的相关分析、幅值分析、频谱分析等时域和频域分析方法。但经典的FFT存在固有缺点,即它虽然在频域范围内是完全局部化的,但是它不包含任何时域信息,因而不适于分析非平稳信号。近年来涌现的各种时频分析方法(短时…

【刷题】初步认识深搜(DFS)

送给大家一句话&#xff1a; 拥有希望的人&#xff0c;和漫天的星星一样&#xff0c;是永远不会孤独的。 -- 《星游记》 初步认识深搜&#xff08;DFS&#xff09; dfs算法二叉树中的深搜Leetcode 129. 求根节点到叶节点数字之和题目描述算法思路 Leetcode 814. 二叉树剪枝题…

Redis-实战篇-缓存更新策略(内存淘汰、超时剔除、主动更新)

文章目录 1、缓存更新策略1.1、内存淘汰1.2、超时剔除1.3、主动更新 2、业务场景&#xff1a;3、主动更新在企业中业务实现有三种方式3.1、Cache Aside Pattern3.1.1、操作缓存和数据库时有三个问题需要考虑&#xff1a;3.1.1.1、删除缓存还是更新缓存&#xff1f;3.1.1.2、如何…

数据同步软件有哪些

数据同步软件有哪些呢&#xff1f;随着企业规模的扩大&#xff0c;企业数据也积累得越来越多&#xff0c;万一发生宕机风险&#xff0c;那么这个损失将不可估量。所以为了容灾备用&#xff0c;我们往往需要将数据同步到另一台备胎服务器上&#xff0c;进行冗余。 那么需要同步的…

centos7.9 python3环境(virtualenv)搭建及所遇错误

人望山&#xff0c;鱼窥荷&#xff0c;真正喜欢想要的&#xff0c;没有一样可以轻易得到。 目录 # 1. 解决版本冲突问题--建议不要跳过(一定要查看软链接是否链接正确) # 2. python3(virtualenv)环境搭建 # 3. virtualenv常用命令 # 4. 所遇错误解析 ## 4.1 遇到 No modul…

惠海 H6246低功耗DC/DC降压型恒压芯片60V降3.3V5V12V 蓝牙模块 单片机供电

1.产品描述 H6246是一种内置60V耐压MOS&#xff0c;支持输入高达48V的高压降压开关控制器&#xff0c;可以向负载提供0.3A的连续电流。H6246支持输出恒定电压&#xff0c;可以通过调节VFB采样电阻来设置输出电压&#xff0c;同时支持最大电流限制&#xff0c;可以通过修改CS采…

操作系统期末复习考题二

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、前言&#x1f680;&#x1f680;&#x1f680;二、正文☀️☀️☀️三、总结&#x1f353;&#x1f353;&#x1f353; 一、前言&#x1f680;&#x1f680;&am…

【资源调度】1-何为调度?

导读&#xff1a;本期是全网最全【资源调度】系列推文的第1期(共50期左右)。我们将对调度的定义与作用、计划与调度的关系、调度问题的拆解做出详细介绍&#xff0c;使大家对【资源调度】问题有了一个整体的认识&#xff0c;为后续的内容奠定基础。 作者1&#xff1a;张哲铭&am…