题解:B4280 [蓝桥杯青少年组国赛 2023] 数学实验
\textup{P9049 [PA 2021] Mopadulo}
li\textup{N} k
知识点:动规,倍增。
\textup{Description}
给定数列,将其中相邻两个相同的数合并而替换成一个大一的数。
求:最终序列中最大的数的最大化。
\textup{Solution}
第一次写这种格式的题解,花了我快
与简化版
:::info[
区间会炸,想想如何改改状态解决?
是否可以将区间右端点转化成什么? :::
:::success[与前人类似地定义
注意此处是左闭右开。
至于为什么?
其实是方便转移和初始化,将两个序列合并的时候就容易了。
最后是若合并不出则值为
:::info[
想一下合并出一个数的条件?
可以往倍增那种嵌套的转移去想。 :::
::::success[
那么找到上一个
所以此处有:
:::info[
并致以感谢。 ::: ::::
:::info[
- 初始化;
- 答案;
- 边界条件。
可以先自己想一下再看。
:::
:::success[
答案即为能合并出来的最大值。
而循环的边界条件约为
此时最多合并出最大值
:::warning[
小心类似 CPH 评测跑出来不容易发现数组越界问题,请使用 Dev。 :::
:::success[
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 5e5 + 249;
const int DTL = 249;
int N, ans;
int a[MAXN], dp[DTL][MAXN];
int main(){
cin >> N;
for( int i = 1; i <= N; i ++ ){
cin >> a[i];
dp[a[i]][i] = i + 1;//初始化
}
for( int k = 2; k <= ( DTL - 49 ) / 2; k ++ ){//这里就是98
for( int i = 1; i <= N; i ++ ){
if( !dp[k][i] ) dp[k][i] = dp[k - 1][dp[k - 1][i]];
//此处我尝试用max并且过了,数据过水,因为取max没有正确性吧。
//贪心来说,应该找最小可能的点才有足够的正确性。
if( dp[k][i] ) ans = max( ans, k );//统计答案
}
}
cout << ans;
return 0;
}
:::
:::info[
审核管理员辛苦了,如果您有什么看不懂、我太弱了所以讲错了的地方,请您在评论区指出或着私信我,我会一定解答并且修改本题解。
如果您觉得本文写的还不错,那可以留个赞吗?
谢谢你看到这里~ :::