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

P11233 [CSP-S 2024] 染色

P11233 [CSP-S 2024] 染色

难度:提高+/省选-

考点:DP

题意

  • 给定 n n n 个数 A i A_i Ai,对 A i A_i Ai 进行染色,只有两种颜色。设 C C C A A A 染色后的数组。

    • 如果 A i A_i Ai 左侧没有预期同色的数,则令 C i = 0 C_i = 0 Ci=0。否则,记其左侧与其最靠的同色数为 A j A_j Aj,若 A i = A j A_i=A_j Ai=Aj,则令 C i = A i C_i=A_i Ci=Ai,否则令 C i = 0 C_i = 0 Ci=0
  • 题目求: ∑ i = 1 n C i \sum_{i=1}^{n} C_i i=1nCi,需要最大化最终得分,请求出最终得分的最大值

分析

20 p t s 20pts 20pts

​ 数据范围: n ≤ 15 n \le 15 n15,暴力枚举每个数字两种染色的情况 2 n 2^n 2n,然后扫描一遍 O ( n ) O(n) O(n),找出最大分值,时间复杂度: O ( T × n × 2 n ) ≈ 9.8 × 1 0 6 ≤ 1 0 8 O(T \times n \times 2^n)≈ 9.8 \times 10^6 \le 10^8 O(T×n×2n)9.8×106108 是可以接受的。

50 p t s 50 pts 50pts

想拿满分,最优性问题要 D P DP DP 解法了。


二维 DP 作为思路启发:

设: f ( i , j ) f(i,j) f(i,j) i i i 个数,第 j j j 个数染色为 j j j 的最大分值。

分类讨论:

  • 1 ∼ a i − 1 1 \sim a_{i-1} 1ai1 都没有相同的数,则贡献 f ( i , 0 ) = f ( i , 1 ) = m a x ( f ( i − 1 , 0 ) , f ( i − 1 , 1 ) ) f(i,0) = f(i,1) = max( f(i-1,0),f(i-1,1) ) f(i,0)=f(i,1)=max(f(i1,0),f(i1,1))

  • 1 ∼ a i − 1 1 \sim a_{i-1} 1ai1 前面存在相同的数,假设以染色为 0 0 0 来看 f ( i , 0 ) f(i,0) f(i,0),前面确定也存在一个染色染色为 0 0 0 的数 ( a i = a j ) (a_i = a_j) (ai=aj)

    这之间所有的数都染色为 1 1 1。确定是前面最靠近相同的数染为相同色,否则在这之间找到相同的数并染色为同色收益也会更大。相同色的数的位置(可预处理出来, O ( n ) O(n) O(n)),则要分 3 3 3 部分进行计算贡献:

    l [ i ] l[i] l[i]:表示数字 i i i 左侧最靠近且相同的数字位置下标。

在这里插入图片描述
部分 ①

​ 位置 ( 1 , l [ a i ] + 1 ) (1,l[a_i]+1) (1,l[ai]+1) 数产生的贡献,其中 l [ a [ i ] ] + 1 l[a[i]] + 1 l[a[i]]+1 染成 1 1 1,即 f ( l [ a i ] + 1 , 1 ) f(l[a_i]+1,1) f(l[ai]+1,1) 的贡献。不用担心(没有被染成 0 0 0)的问题,因为 f ( l [ a i ] , 1 ) f( l[a_i],1 ) f(l[ai],1) 会选择最优的策略,那么(此时可以选择不和 l [ a i ] + 1 l[a_i]+1 l[ai]+1)染为同色。

部分 ②

​ 位置 $ l[a_i]+2 \sim i-1 $ 的数产生的贡献,这贡献会把区间 l + 1 ∼ i − 1 l+1 \sim i-1 l+1i1 染为同色产生的贡献计算上,设 s i s_i si 1 ∼ i 1 \sim i 1i 位置上染为同色的贡献。那么 l + 1 ∼ i − 1 l+1 \sim i-1 l+1i1 全部染为同色所产生的的贡献,或可以表示为 l + 2 ∼ i − 1 l+2 \sim i-1 l+2i1 数产生的贡献 ( s i − 1 ∼ s l + 1 ) (s_{i-1} \sim s_{l+1}) (si1sl+1)

部分 ③

​ 在 i i i 位置上的数,贡献就是 a i a_i ai

上述对应的 3 个部分,可以表示如下图所示:

在这里插入图片描述
对于前面存在相同数字的贡献,总结:
f ( i , 0 ) = { f ( l i + 1 , 1 ) ( s i − 1 − s l i + 1 ) a i f(i,0) = \left\{ \begin{array}{lc} f( l_{i+1},1 )\\ (s_{i-1} - s_{l_i+1})\\ a_i \end{array} \right. f(i,0)= f(li+1,1)(si1sli+1)ai
特判 a i = a i − 1 a_i = a_{i-1} ai=ai1 的情况,即 f ( i , 0 ) = f ( i − 1 , 0 ) + a i f(i,0) = f(i-1,0)+a_i f(i,0)=f(i1,0)+ai f ( i , 1 ) = f ( i − 1 , 1 ) + a i f(i,1) = f(i-1,1) + a_i f(i,1)=f(i1,1)+ai

在产生贡献和不产生贡献中最大分值中取 m a x max max:
{ f ( i , 0 ) = m a x ( f ( i − 1 , 0 ) , f ( i − 1 , 1 ) , a i + f ( l i + 1 , 1 ) + ( s i − 1 − s l i + 1 ) ) f ( i , 1 ) = m a x ( f ( i − 1 , 0 ) , f ( i − 1 , 1 ) , a i + f ( l i + 1 , 0 ) + ( s i − 1 − s l i + 1 ) ) a n s = m a x ( f ( n , 0 ) , f ( n , 1 ) ) \left\{ \begin{array}{lc} f(i,0) = max( f(i-1,0), f(i-1,1), a_i + f(l_{i}+1,1) + (s_{i-1} - s_{l_{i}}+1) )\\ f(i,1) = max( f(i-1,0), f(i-1,1), a_i + f(l_{i}+1,0) + (s_{i-1} - s_{l_{i}}+1) )\\ \end{array} \right. \newline ans = max( f(n,0), f(n,1) ) {f(i,0)=max(f(i1,0),f(i1,1),ai+f(li+1,1)+(si1sli+1))f(i,1)=max(f(i1,0),f(i1,1),ai+f(li+1,0)+(si1sli+1))ans=max(f(n,0),f(n,1))

最开始就是如上的思路去解题的,但想了一下第二个维度有必要开么?

感觉可以去掉,再思考一下。


返璞归真,简单的状态表示:

​ 设状态 f i f_i fi 表示前 i i i 位数的最大分值和。显然对于每一个位置 i i i 可以令 f i = f i − 1 f_i=f_{i-1} fi=fi1

​ 用 l i l_i li 记录 i i i 上一次出现的位置,初始化令所有的 l i = 0 l_i = 0 li=0,每遍历到一个位置,动态更新 l a i = i l_{a_i} = i lai=i。然后枚举区间更新 f i f_i fi,也可以预处理 g g g 数组 g [ i ] [ j ] g[i][j] g[i][j] 表示区间 [ i , j ] [i,j] [i,j] 的染色为相同时的最大分值之和,复杂度是 O ( n 2 ) O(n^2) O(n2) n ≤ 1 0 3 n \le 10^3 n103 50 p t s 50pts 50pts 到手。

参考代码

// 50pts
#include <bits/stdc++.h>
const int N = 2e3 + 5;int n, T;
int a[N], lst[N];  // lst[i]:表示数字 i 最靠近 i 左侧的数字位置
int f[N], g[N][N]; // f[i] ::: 表示考虑前 i 个数贡献的最大分值之和int main()
{std::cin >> T;while (T--){memset(a, 0, sizeof a), memset(lst, 0, sizeof lst), memset(f, 0, sizeof f), memset(g, 0, sizeof g);std::cin >> n;for (int i = 1; i <= n; i++)std::cin >> a[i];for (int i = 1; i <= n; i++) // 构造 区间 [i,j] 染色相同的最大分值之和for (int j = i + 1; j <= n; j++){g[i][j] = g[i][j - 1];if (a[j] == a[j - 1])g[i][j] += a[j];}for (int i = 1; i <= n; i++){if (lst[a[i]] == 0) // 前 i-1 位不存在相同的数字 a[i]{lst[a[i]] = i;   // 更新数字 a[i] 最后一次出现的下标f[i] = f[i - 1]; // 继承前 i-1 位的最大分值}else{f[i] = std::max(f[i - 1], std::max(f[lst[a[i]] + 1], f[lst[a[i]]]) + a[i] + g[lst[a[i]] + 1][i - 1]);lst[a[i]] = i; // 更新数字 a[i] 最后一次出现的下标}}std::cout << f[n] << "\n";}return 0;
}

100 p t s 100pts 100pts

n ≤ 1 0 6 n\le 10^6 n106 g [ i ] [ j ] g[i][j] g[i][j] 开不下这么大的数组。用前缀和优化,每当 a i = a i − 1 a_i = a_{i-1} ai=ai1 时候,更新前缀和数组 s i s_i si。最后对于 a i a_i ai 如果 l a i l_{a_i} lai 存在,则对 f i f_i fi 转移:
f i = ( 1 ≤ i ≤ n ) m a x { f l a i + 1 , a i , ( s i − s l a i ) } f_i = (1 \le i \le n ) \space max\{ f_{l_{a_i}+1}, a_i,( s_i-s_{l_{a_i}}) \} fi=(1in) max{flai+1,ai,(sislai)}
参考代码

#include <bits/stdc++.h>
#define ll long longconst int N = 1e6 + 10;
// f[i] ::: 表示前 i 个数,最大分值之和, lst[i] ::: 表示数字 i 前面最靠近的相同数字位置, s[i] ::: 表示前 i 个数染相同颜色的总贡献
ll f[N], s[N], lst[N], a[N];
ll n, T;int main()
{std::ios::sync_with_stdio(false), std::cin.tie(nullptr);std::cin >> T;while (T--){memset(f, 0, sizeof f), memset(s, 0, sizeof s), memset(lst, 0, sizeof lst), memset(a, 0, sizeof a);std::cin >> n;for (int i = 1; i <= n; i++)std::cin >> a[i];// 构造 1~i 个数,全部数字染色相同时的最大分值之和for (int i = 2; i <= n; i++)s[i] = (a[i] == a[i - 1] ? s[i - 1] + a[i] : s[i - 1]);for (int i = 1; i <= n; i++) // 枚举数字的位置 i{f[i] = f[i - 1]; // 省去判断,默认继承if (lst[a[i]])   // 如果前面存在相同的数字, 则将 3 部分的贡献作对比更新f[i] = std::max(f[i], f[lst[a[i]] + 1] + a[i] + s[i] - s[lst[a[i]] + 1]);lst[a[i]] = i; // 更新数字 a[i] 出现的位置}std::cout << f[n] << "\n";}return 0;
}

相关文章:

P11233 [CSP-S 2024] 染色

P11233 [CSP-S 2024] 染色 难度&#xff1a;提高/省选-。 考点&#xff1a;DP。 题意&#xff1a; 给定 n n n 个数 A i A_i Ai​&#xff0c;对 A i A_i Ai​ 进行染色&#xff0c;只有两种颜色。设 C C C 为 A A A 染色后的数组。 如果 A i A_i Ai​ 左侧没有预期同…...

图传推流学习(敬请期待)

图传推流简介 1.RTSP、RTP与RTCP2.搭建rtsp服务器&#xff08;资源下载&#xff09;3.搭建rtsp服务器&#xff08;搭建过程&#xff09; 1.RTSP、RTP与RTCP RTSP&#xff08;Real Time Streaming Protocol&#xff09;、RTP&#xff08;Real-time Transport Protocol&#xff0…...

【JavaGuide】十大经典排序算法总结

冒泡排序 算法步骤 不断的两两比较&#xff0c;这样当前最大的元素总是会排在最后面。所以称为冒泡。 图解算法 代码实现 public static int[] bubbleSort(int[] arr) {// i是排好了几个数for (int i 1; i < arr.length; i) {// flag标记当前循环是否调整了顺序&#xff0c…...

程序中怎样用最简单方法实现写excel文档

很多开发语言都能找到excel文档读写的库&#xff0c;但是在资源极其受限的环境下开发&#xff0c;引入这些库会带来兼容性问题。因为一个小功能引入一堆库&#xff0c;我始终觉得划不来。看到有项目引用的jar包有一百多个&#xff0c;看着头麻&#xff0c;根本搞不清谁依赖谁。…...

《机器学习与人类学习:比较、融合与未来展望》

《机器学习与人类学习&#xff1a;比较、融合与未来展望》 一、引言二、机器学习的概念与发展&#xff08;一&#xff09;机器学习的定义与分类&#xff08;二&#xff09;机器学习的发展历程&#xff08;三&#xff09;机器学习的应用领域 三、人类学习的本质与过程&#xff0…...

Mysql 8.4.3LTS 的离线部署

文章目录 一、部署环境资源配置 二、下载地址版本选择 三、部署详情1. 上传安装包2. 解压软件包3. 安装mysql3.3.1 创建mysql用户与用户组3.3.2 授权安装文件夹3.3.3 安装libaio依赖 &#xff08;坑&#xff09;ubuntu24.04 中关于libaio的坑 3.3.4 初始化Mysql数据库3.3.5 编辑…...

h5项目打包上线报错404文件找不到

配置一下路由就可以了 1.找到项目里的这个文件 2.滑到最下面‘源码视图’ 3.找到base&#xff0c;没有的话写上一个&#xff0c;保存后打包就可以了 "h5" : {"router" : {"base" : "./"}}...

mysql上课总结(5)(MySQL的完整性约束(详细介绍))

目录 一、完整性约束。 &#xff08;1&#xff09;概念与目的。 <1>概念。 <2>目的。 &#xff08;2&#xff09;各个约束的详细&#xff08;表格&#xff09; &#xff08;3&#xff09;各个约束的简要总结。 <1>主键约束。 <2>唯一约束。 <3>非…...

复原IP地址

分割字符串的姐妹题 题目&#xff1a;93. 复原 IP 地址 - 力扣&#xff08;LeetCode&#xff09; 题解&#xff1a;代码随想录 代码&#xff1a; class Solution {List<String> resnew ArrayList<>();public List<String> restoreIpAddresses(String s) …...

Effective C++ 学习笔记二

Effective C 学习笔记二 文章目录 Effective C 学习笔记二别让异常逃离析构函数绝不在构造和析构的过程中调用virtual函数令operator 返回一个reference to *this在operator中处理"自我赋值"C四种转换 别让异常逃离析构函数 C 并不禁止析构函数吐出异常&#xff0c;…...

以「JIMUMETA元宇宙体验馆」为例,探讨有哪些元宇宙场景?

让我们以「JIMUMETA元宇宙体验馆」为例&#xff0c;深入探讨元宇宙场景中提供的产品与服务。该体验馆由视创云展精心打造&#xff0c;集成了企业主展馆、元宇宙虚拟活动分会场、品牌展示分会场、线上论坛会场以及会议室接待会客等多重功能&#xff0c;旨在全方位满足企业发布会…...

RHCE的练习(8)

动态网站 lnmp&#xff08;LAMP&#xff09; 解析index.php界面 &#xff08;1&#xff09;预配&#xff0c;确保服务能够被访问 systemctl stop firewalld setenforce 0 &#xff08;2&#xff09;安装nginx服务 mount /dev/sr0 /mnt cat /etc/yum.repos.d/base.repo dnf …...

yocto是如何收集recipes,如何加入现有的bb文件

yocto通常是如何收集recipes: 在Yocto中&#xff0c;通过以下方式收集recipes&#xff1a; 层&#xff08;Layers&#xff09; Yocto项目使用层来组织recipes。层是包含配置文件、recipes和其他相关文件的目录结构。每个层有自己的目录&#xff0c;其中 recipes-* 目录用于存…...

[运维] 服务器本地网络可用性检查脚本

引言 在日常活动中&#xff0c;我遇到过一个令人头疼的问题。测试使用的远程终端在第二天继续使用时可能就发生无法与外网通信的情况&#xff0c;往往连上终端后在拉取资源时才能发现。这导致每次使用前都需要手动检查网络状况&#xff0c;增加了不必要的麻烦。为了简化这一过…...

MYSQL-显示信息关于服务器插件语法(二十五)

13.7.5.25 SHOW PLUGINS 语句 SHOW PLUGINSSHOW PLUGINS 显示信息 关于服务器插件。 SHOW PLUGINS 输出示例&#xff1a; mysql> SHOW PLUGINS\G *************************** 1. row ***************************Name: binlogStatus: ACTIVEType: STORAGE ENGINE Librar…...

【线下培训】龙信受邀参加开封市公安局举办的电子数据取证培训班

文章关键词&#xff1a;电子数据取证、手机取证、云取证、国产化取证 为了提升开封市公安机关在互联网电子数据取证分析方面的专业能力&#xff0c;龙信为开封市公安机关量身打造了一场高质量的电子数据取证分析技能培训课程。 本次培训课程不仅涵盖了电子数据取证的基础理论、…...

软件测试工程师面试整理 —— 编程与自动化!

在软件测试领域&#xff0c;编程与自动化是提升测试效率、覆盖率和可靠性的关键因素。掌握编程技术和自动化测试框架&#xff0c;能够帮助测试人员有效地执行大量重复性测试任务&#xff0c;并迅速反馈软件的质量状况。以下是编程与自动化在测试中的主要应用及相关技术介绍&…...

【鸿蒙新闻】10月29日警用鸿蒙开发者大会在北京胜利召开,开启智慧应用新时代!

10月29日&#xff0c;在公安部科技信息化局、公安部装备财务局指导下&#xff0c;由公安部第一研究所主办&#xff0c;鼎桥通信技术有限公司、OpenHarmony生态委员会及公共安全专委会协办的警用鸿蒙开发者大会在北京胜利召开。会议以“拥抱警鸿创新生态 开启智慧应用新时代”为…...

java.io.IOException: Too many open files

java.io.IOException: Too many open files 前言&#xff1a; 项目最近报 java.io.IOException: Too many open files 问题&#xff0c;大概意思是&#xff1a;意味着你的应用程序尝试打开的文件描述符数量超过了系统允许的最大数量&#xff0c;在linux中每个进程打开的文件描…...

ElementUI el-form表单多层数组的校验

问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; ElementUI el-form表单多层数组的校验 页面效果&#xff1a; 数据结构&#xff1a; addform: {code: ,type: ,value: ,state: 1,remark: ,fieldList: [{fieldCode: ,resolverEntities: [{resolverType: , re…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...