CodeForces 713C Sonya and Problem Wihtout a Legend (策略问题+DP)*

这是一道关于如何将序列转化为单调递增序列的问题,通过两种操作(加一或减一)求解最少操作次数。通过分析,发现可以将序列映射到其子集,并且至少有一个数不需要改变。在不减少的情况下,从不变的那个数开始,若后续数小于它,则结论可以延续;若大于,可以通过某些策略到达序列集合外的一个数,达到最优解。此外,通过技巧性地处理数组,使得不减的情况满足单调性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意

给定一个序列,现在有两种操作,

一种是使序列中某一个数加一,一种是使其减一.

问把这个序列弄成单调递增的最少操作次数是多少.

题目分析 

这题我是看题解的,发现是蛮经典的一道题.

首先考虑不降序列,那么我们如果暴力DP那么数据范围

是九次方存不下,我们需要找到一种可以包含所有可能转移到的状态的

空间而使空间开的下.

我们可以证明序列最后映射成的,是其原本序列的子集.

首先可以肯定的是至少有一个数是不用变的,那么从这个数开始,

对于这个数,设为x,假设下一个数小于x,那么很显然结论可以延扩下去,

如果是大于,可能存在一种情况是两个数各走一些步数来到达一个不归于

序列集合的一个数来达到目的,可以证明这种情况的话那么下面的数肯定是在这个目的数的

上方否则明显存在更优解,如果这个目的数在两者之间可以用一个不差的策略替换即两数都归为

下一个数值.

口胡了那么久,太严格证明本弱又不会,,想到哪里说到哪里吧,仅供参考.

 

不减的情况我们完成了,对于递增的情况有个技巧就是把a数组减去其对应的序号,

详见代码,这样任意原序列的不减在变化后的序列中都是单调的了.

#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long l
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值