CF2031D - Penchick and Desert Rabbit

CF2031D - Penchick and Desert Rabbit

思路

妙妙妙妙秒极了的一道思维题。

发现 i 左侧能跳到的都高于它,右侧能跳到的都低于它,考虑如何利用这个性质。

fi 表示 1i 的最大高度,gi 表示 in 的最小高度,对应位置分别记为 x,y

思考有哪些途径可以更新 i 的答案。

一种是可以直接跳到 fi

另一种是借助右侧的某个点 j 跳到更高的位置,例如当前在 3, 局势是 7 310 2,最优的走法是 3210。发现这还不够,还有可能是 7 310 4,最优的走法是 37104。先往前跳一步,再往后跳更低的,再跳到更高的位置。

所以总结一下借助右侧点更优的条件,容易发现是 fi>gi+1,实际上这也是充要的,因为 ax>ay,我们可以通过 ixy? 跳到不劣于 x 的位置。所以 i 跳到 j 一定不劣。

整理一下思路:

ansi={fifigi+1ansi+1fi>gi+1

时间复杂度 O(n)

#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=(r);++i)
#define G(i,r,l) for(int i(r);i>=(l);--i)
using namespace std;
using ll = long long;
const int N = 5e5 + 5;
const int inf = 0x3f3f3f3f;
int n, T;
int f[N], g[N], a[N], ans[N];
signed main(){
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin >> T;
	while(T --){
		cin >> n;
		F(i, 1, n) cin >> a[i];
		F(i, 1, n) f[i] = max(f[i - 1], a[i]);
		g[n] = a[n]; G(i, n - 1, 1) g[i] = min(g[i + 1], a[i]);
		ans[n] = f[n];
		G(i, n - 1, 1){
			if(f[i] > g[i + 1]) ans[i] = ans[i + 1];
			else ans[i] = f[i];
		}
		F(i, 1, n) cout << ans[i] << ' ';
		cout << '\n';
	}
	return fflush(0), 0;
}

总结

赛时有想过记录前缀 max 和后缀 min,也想过 3 10 2 这种情况,但是没有想过 7 3 10 4 这种情况(借助右侧点之前还要先借助一下左侧点)。还有一点是没有去观察哪些位置只能往前或往后跳(虽然这是显然的),以上两点这可能是没能成功运用 fg 的主要原因。

继续锻炼自己的能力!从特殊情况入手!充分挖掘好的样例!

posted @   superl61  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示