zoukankan      html  css  js  c++  java
  • 题解——额外的体力(单调队列优化DP)

    题解——额外的体力(单调队列优化DP)

    这就是道模板题,然而ssw02考场单调队列写挂了(ssw02是真的菜)
    明天还有学长的ACM赛制比赛,幸好有 tqr06 组队。


    题面

    现在你所的旅行团将要走一段路 ,具体来说,这条路被分成了 N段,每一段都有个凸出程度ai。
    这个旅行团有 T个人,每个有一最大步 幅 Ki,也就是说若当前你在 ,也就是说若当前你在 ,也就是说若当前你在 x段,下一次你最多走到x +Ki段
    当一个人走下坡路时, 走下坡路时这个人将自在的通过,反之将消耗1点额外的体力。
    问每个人最少消耗的体力 。

    每次可以在前K段中找。单调队列优化后时间就可以过。
    主要提一下:
    在排序的时候,以消耗体力作为第一关键字,维护单调递增,再以高度作为第二关键字,维护单调递减。

    AC代码1(ssw02)

    #include<bits/stdc++.h>
    using namespace std;
    const  int  N =  2000001 ;
    inline int read(){
    	int s = 0 ;
    	char g = getchar() ;
    	while(g>'9'||g<'0')g=getchar() ;
    	while(g>='0'&&g<='9')s=s*10+g-'0', g = getchar() ;
    	return s ;
    }  
    int  n , T , k , a[ N ] , loc[ N ], q[ N ] , tot = 0   ;
    int f[ N ] ;
    int main()
    {
    	freopen("extra.in","r",stdin);
    	freopen("extra.out","w",stdout);
        n = read() ;
        for(int i = 1;i <= n ; i++ ) scanf("%d",&a[ i ]);
        T = read() ;
        while( T-- ){
        	k = read() ;
        	int  head = 1 , tail = 0 ;
            memset( q , 0 , sizeof(q));
            memset( loc, 0 , sizeof(loc));
            memset( f , 0 , sizeof(f) ) ; 
            head = 1 , tail = 0 ; tot = 0 ;f[ 1 ] = 0 ;q[++tail] = 0 ;loc[ tail ] = 1 ;
            for( int i = 2 ; i <= n ; i++ ){
                while( head <= tail && i - loc[ head ] > k ) head++ ; //队不为空 且 队首太远 出队
    			( a[ loc[head] ]>a[ i ] )?f[ i ]=q[head]:f[ i ]=q[head]+1 ;
                while( 1 ){//这里写得太麻烦了
                	if( !(head <= tail ) || f[ i ] > q[ tail ] )break ;
                	if( f[ i ]==q[ tail ]&&a[ i ]<=a[ loc[ tail ] ])break ; 
                	if( head <= tail && a[ i ] > a[ loc[tail] ] && f[ i ] == q[ tail ] )tail--;
                	if( head <= tail && f[ i ] < q[ tail ] )tail-- ;
                }//清队尾 
    			q[ ++tail ] = f[ i ] ; loc[ tail ] = i ; //将新元素入队
            }
            //for( register int i = 1 ; i <= n ; ++i )printf("%d ",f[i] ) ;
            printf("%d
    ",f[ n ]) ;
        }
        return 0;
    }
    

    优美的std

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    #define dnt long long 
    #define inf 0x3f3f3f3f
    
    const int N = 1e6 + 11;
    
    int n, K, f[N], q[N], hd = 1, tl = 0, a[N];
    
    int main() {
    	cin>>n;
    	for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    	int T; cin>>T;
    	while( T -- ) {
    		scanf("%d", &K); memset(f, inf, sizeof(f));
    		hd = 1, tl = 0;
    		f[1] = 0; q[++tl] = 1;
    		for(int i = 2; i <= n; i++) {
    			while(hd <= tl && q[hd] + K < i) ++ hd;
    			f[i] = f[q[hd]] + ((a[q[hd]] <= a[i]) ? 1 : 0);
    			while((hd <= tl) && ((f[q[tl]] > f[i]) || ((f[q[tl]] == f[i]) &&( a[q[tl]] < a[i]))))--tl;
    			q[++tl] = i;
    		}
    		printf("%d
    ", f[n]);
    	}
    	return 0;
    }
    

    有疑惑和建议,可以留下评论或私我。(这道题就是个板子)

    如果你喜欢我的文章,请点赞支持,谢谢。

  • 相关阅读:
    看完动画你还会不懂 快速排序么
    看动画轻松理解时间复杂度(一)
    LeetCode Animation 题目图解汇总(持续更新中...)
    分而治之,归并排序的动画演示
    在Object-C中学习数据结构与算法之排序算法
    iOS面试准备之思维导图
    .net core跨域设置
    .NET Core WebAPI Swagger使用
    vue-resource emulateJSON的作用
    百度地图API简单初始化
  • 原文地址:https://www.cnblogs.com/ssw02/p/11215791.html
Copyright © 2011-2022 走看看