acm-(dp、单调栈)Codeforces Round #669 (Div. 2) D. Discrete Centrifugal Jumps

题面
传送门
d p [ i ] dp[i] dp[i]表示到达第 i i i个城市要的最小跳跃次数,首先只看 1 、 2 1、2 12的转移条件,我们容易发现枚举 i i i的时候,一旦 a [ i − 1 ] < a [ i ] a[i-1]<a[i] a[i1]<a[i],那么 d p [ i − 1 ] dp[i-1] dp[i1]只会对 d p [ i ] dp[i] dp[i]产生贡献,因为 a [ i ] a[i] a[i]阻挡了从 a [ i − 1 ] a[i-1] a[i1]往后继续跳。不过对于前面第一个 a [ j ] ≥ a [ i ] a[j]\ge a[i] a[j]a[i] j j j,它是最左边的一个能转移到 i i i的位置,对于 1 ∼ j − 1 1\sim j-1 1j1的数也因为 a [ j ] ≥ a [ i ] a[j]\ge a[i] a[j]a[i]的原因导致无法转移到 i i i,不过它们存在机会转移到 i i i以后的位置,因此我们维护一个单调递减的栈即可,若当前元素大于栈顶元素,那么转移一下然后pop掉即可。

对于第 3 3 3个转移条件跟第 2 2 2个条件是对称的,所以再维护一个单调递增的栈即可。

int dp[maxn],a[maxn];
int up[maxn],down[maxn],totu,totd;
int main(){
	int n=rd();
	up[++totu]=down[++totd]=1;
	a[1]=rd();
	memset(dp,0x3f,sizeof(dp));
	dp[1]=0;
	FOR(i,2,n+1){
		int u=a[i]=rd();
		while(totd && u>a[down[totd]]){
			dp[i]=min(dp[i],dp[down[totd--]]+1);
		}
		while(totu && u<a[up[totu]]){
			dp[i]=min(dp[i],dp[up[totu--]]+1);
		}
		if(totd){
			dp[i]=min(dp[i],dp[down[totd]]+1);
		}
		if(totu){
			dp[i]=min(dp[i],dp[up[totu]]+1);
		}
		if(a[down[totd]]==u)totd--;
		if(a[up[totu]]==u)totu--;
		down[++totd]=i;
		up[++totu]=i;
	}
	wrn(dp[n]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值