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

P7958 [COCI2014-2015#6] NEO

题目大意

翻译的基本题面就不多说了,我们来大概分析一下题目。

  • 序列会变回来:我们可以观察到,在 n n n 次变换后,序列会还原。也就是说,两个循环在同一个 i i i 上操作的序列是一样的。
  • 下标的空间:然后我们再分析一下不难发现,下标是一大一小,也就是 min ⁡ ( I D i , I D i + 1 ) \min\left(ID_{i},ID_{i+1}\right) min(IDi,IDi+1) min ⁡ ( I D i , I D i + 1 ) + 1 \min\left(ID_{i},ID_{i+1}\right)+1 min(IDi,IDi+1)+1,所以我们求 I D i ID_i IDi 时,去求 I D i − 1 ID_{i-1} IDi1 就好了。聪明的小朋友想到动态规划了,那么再找找。
  • 连续性:再找一找就可以发现就是选择一些边,那么就可以知道状态之间是关联的。

思路概述

经过了上面的思考,我们就不难可以发现,这道题肯定用动态规划。我总结了两种方法供大家食用:

强行 dp

这种思路是我一开始想出来的,其实挺好设的。我们就设 f i , j f_{i,j} fi,j 表示在 i i i 的时候选 j j j 所能取到的最大贡献,所以我们就可以得到一个转移方程。
f i , j = max ⁡ k = 1 n − 1 ( f i − 1 , k + A min ⁡ ( j , k ) − A max ⁡ ( j , k ) + 1 ) f_{i,j}=\max_{k=1}^{n-1}\left(f_{i-1,k}+A_{\min\left(j,k\right)}-A_{\max\left(j,k\right)}+1\right) fi,j=k=1maxn1(fi1,k+Amin(j,k)Amax(j,k)+1)
但是肯定有同学一眼丁真,发现时间复杂度太大了,所以我们优化成这个样子:
f i , j = max ⁡ ( A j + max ⁡ k = j n − 1 ( f i − 1 , k − A k + 1 ) − A j + 1 + max ⁡ k = 1 j ( f i − 1 , k + A k ) ) f_{i,j}=\max\left(A_j+\max_{k=j}^{n-1}\left(f_{i-1,k}-A_{k+1}\right)-A_{j+1}+\max_{k=1}^{j}\left(f_{i-1,k}+A_{k}\right)\right) fi,j=max(Aj+k=jmaxn1(fi1,kAk+1)Aj+1+k=1maxj(fi1,k+Ak))
然后后面的东西我们可以使用前缀或者是后缀和搞定。然后我们上一下核心代码:

pre[0]=suf[n]=-1e9;
for(i=1;i<=n;++i,solve()){
   for(k=1;k<n;++k){
   	if(pre[k-1]>=f[i-1][k]+A[k]){
   		pre[k]=pre[k-1];
   		pref[k]=pref[k-1];
   	}else{
   		pre[k]=f[i-1][k]+A[k];
   		pref[k]=k;
   	}
   }
   for(k=n-1;k;--k){
   	if(suf[k+1]>=f[i-1][k]-A[k+1]){
   		suf[k]=suf[k+1];
   		suff[k]=suff[k+1];
   	}else{
   		suf[k]=f[i-1][k]-A[k+1];
   		suff[k]=k;
   	}
   }
   for(j=1;j<n;++j){
   	int p=pre[j]-A[j+1],s=suf[j]+A[j];
   	if(p>=s){
   		f[i][j]=p;
   		trans[i][j]=pref[j];
   	}else{
   		f[i][j]=s;
   		trans[i][j]=suff[j];
   	}
   }
}

但是,这个空间复杂度不够优秀,所以我们再换一种。

正解

那么我们可以对于每一个 i i i ,我们可以设
i d 1 = min ⁡ ( I D i , I D i + 1 ) , i d 2 = m i n ( I D i , I D i + 1 ) id_1=\min(ID_i,ID_{i+1}),id2=min(ID_i,ID_{i+1}) id1=min(IDi,IDi+1),id2=min(IDi,IDi+1)
所以,我们就可以得到 s u m = A i d i − A i d 2 + 1 sum=A_{id_i}-A_{id_2+1} sum=AidiAid2+1
同时,这也让我们想到了差分这件事情,所以我们可以构建出一个 ( n − 1 ) × n \left(n-1\right)\times n (n1)×n 的矩阵,每一行都是旋转后记录的差分数组。但是动态规划的数组怎么设计呢?其实很简单,设 f i , j , k f_{i,j,k} fi,j,k 表示走到了 ( i , j ) \left(i,j\right) (i,j) 这个位置的时候,方向是 k k k 的最长路径,所以就有如下的转移方程。
f i , j , 0 = max ⁡ ( f i − 1 , j , 0 / 1 / 2 + B i , j ) f i , j , 1 = max ⁡ ( f i , j + 1 , 0 / 1 + B i , j ) f i , j , 2 = max ⁡ ( f i , j − 1 , 0 / 2 + B i , j ) f_{i,j,0}=\max\left(f_{i-1,j,0/1/2}+B_{i,j}\right) f_{i,j,1}=\max\left(f_{i,j+1,0/1}+B_{i,j}\right) f_{i,j,2}=\max\left(f_{i,j-1,0/2}+B_{i,j}\right) fi,j,0=max(fi1,j,0/1/2+Bi,j)fi,j,1=max(fi,j+1,0/1+Bi,j)fi,j,2=max(fi,j1,0/2+Bi,j)
代码就不贴了。


http://www.kler.cn/news/288325.html

相关文章:

  • 如何处理海量数据
  • 事半功倍:利用增强现实提高工作效率
  • [AcWing]-完全背包问题-动态规划
  • RabbitMQ的TLL
  • Mac OS X 如何升级系统自带的 Ruby
  • 教程:使用显卡MX250做YOLO目标检测(定位)滑块缺口,包括获取数据集,对数据集手动标注,训练的代码,推理的代码,超多细节,你的第一次YOLO绝佳体验!
  • 微信小程序认证和备案
  • 比特币详解
  • (大三上_游戏开发设计模式_上课_1)多态练习_计算机
  • CUDA编程08 - 并行编程思维
  • 【React 简化路由的生成的方式
  • kafka3.7.1 单节点 KRaft部署测试发送和接收消息
  • 深入解析FPGA在SOC设计中的核心作用
  • 深入探讨Java中的分布式事务管理:实现、挑战与最佳实践
  • 超声波的应用
  • 【python计算机视觉编程——4.照相机模型与增强现实】
  • sqlite3的db.wait方法:等待所有查询完成
  • PyQt6 / PySide 6 实现可拖拽的多标签页 web 浏览器【1】(有 Bug)
  • Ansible 自动化运维项目
  • 如何在Mac上使用VMware配置Windows虚拟机
  • C#绘制常用工业控件(仪表盘,流动条,开关等)
  • 浅谈分库分表的“读扩散”问题
  • 第二十章 rust多平台编译
  • 博客自建(带避坑指南)4:hexo文章页设置和动画魔改设置
  • 数据防泄密知识集锦丨八个实用数据防泄密软件,你知道吗?
  • TikTok直播限流与网络有关系吗?怎么解决?
  • 【Apache Doris】数据均衡问题排查指南
  • 解锁 Redis:探索连接策略、数据编码与性能秘诀
  • Vue3项目开发——新闻发布管理系统(五)
  • 腾讯云技术深度解析:AI代码助手与微服务架构的实践应用