zoukankan      html  css  js  c++  java
  • CF1407D Discrete Centrifugal Jumps 题解

    蒟蒻语

    写了 \(100\) 行的 线段树上 ST 表维护二分维护单调栈维护 dp, 结果最后发现只要俩单调栈就好了 = =

    蒟蒻解

    首先 \(dp_i\) 表示从 \(1\) 楼到 \(i\) 楼要跳几次。

    题目中有 3 个条件, 对三个条件分别设 \(dp\) 方程。

    第一个很显然, 就是 : \(dp_i = dp_{i - 1} + 1\)

    第二个怎么弄呢?

    考虑看有哪些点是可能来更新这个点的。

    假设 \(x\) 位置可以来更新 \(i\) 位置。那么 \(h_x > max(h_{x+1}, h_{x + 2} ... h_{i - 1})\)

    考虑使用单调栈。单调栈里面的节点满足严格递增。 这样 \(x\) 就一定是单调栈中的节点了

    因为要求 \(h_i > max(h_{x+1}, h_{x + 2} ... h_{i - 1})\),所以如果单调栈中有一个数比他大,那么单调栈中在他之后的节点就不能更新他了。

    可以在单调栈中边弹点边更新答案。

    第三个条件和第二个几乎一样,不说了。

    蒟蒻码

    细节看代码吧。

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 3e5 + 7;
    
    int n, m, s[N], dp[N], atot, a[N], btot, b[N];
    int main() {
    	scanf("%d", &n);
    	for(int i = 1; i <= n; i++) scanf("%d", &s[i]);
    	memset(dp, 0x3f, sizeof(dp));
    	a[++atot] = 1, b[++btot] = 1, dp[1] = 0;
    	for(int i = 2; i <= n; i++) {
    		dp[i] = dp[i - 1] + 1;
    		while(atot && s[i] >= s[a[atot]]) {
    			if(s[i] != s[a[atot]]) dp[i] = min(dp[i], dp[a[atot - 1]] + 1);
    			--atot;
    		}
    		while(btot && s[i] <= s[b[btot]]) {
    			if(s[i] != s[b[btot]]) dp[i] = min(dp[i], dp[b[btot - 1]] + 1);
    			--btot;
    		}
    		a[++atot] = i, b[++btot] = i;
    	}
    	printf("%d\n", dp[n]);
    	return 0;
    }
    
  • 相关阅读:
    LeetCode 169
    LeetCode 152
    LeetCode 238
    LeetCode 42
    LeetCode 11
    GDB基本调试
    小咪买东西(最大化平均值)
    codeforces 903D
    hdu 5883
    hdu 5874
  • 原文地址:https://www.cnblogs.com/zkyJuruo/p/13666216.html
Copyright © 2011-2022 走看看