• POI 2014 little bird


    题目简介见https://www.luogu.org/problemnew/show/P3572

    dp 方程应该很好写  (a 数组 为 树的高度)

    j + k >= i  且 j < i

    a[j] > a[i]   时 f[i] = min (f[i] , f[j]) ;

    a[j] <= a[i] 时 f[i] = min (f[i] , f[j] +1 );

    但是 复杂度 N^2*q  老爷机 受不了;

    只能优化喽 ;

    推断1 : 如果有 j > k 且  f[j] < f[k]  那么 j 永远比 k 优;

    此时可以用单调队列; 执行推断1

    但是 我们还要考虑树的高度;

    推断2 :当单调队列中  j > k  且 f[j] == f[k]  且 a[j] > a[k]  那么j 比 k 更优秀 ;

    终上所述 我们维护f非严格递增 , 当f相同时 , 维护a递减;

    代码:

    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<stack>
    #include<cstring>
    using namespace std;
    #define M 1000100
    #define ll long long
    int n , m , f[M] , a[M] , maxn , high , k , q[M] , l , r;
    void solve(){
        l = r = 1; q[1] = 1;
        memset(f , 0x3f , sizeof(f));
        f[1] = 0; 
        for (int i = 2 ; i <= n ; ++i){
            while (l <= r && q[l] + k < i ) ++l;
            if (a[q[l]] > a[i]) f[i] = f[q[l]];
            else f[i] = f[q[l]] + 1;
            while (f[i] < f[q[r]] && r >= l) --r;
            while (f[i] == f[q[r]]){
                if (a[i] >= a[q[r]]) --r;
                else break;
            } q[++r] = i;
        }
        printf ("%d
    " , f[n] );
    }
    int main(){
        freopen("c1.in" , "r" , stdin);
    //    freopen("A.out" , "w" , stdout);
        scanf("%d" , &n);
        for (int i = 1 ; i <= n ; ++i) scanf("%d" , a + i);
        scanf("%d" , &m);
        while (m--){
            scanf("%d" , &k);
            solve();
        }
        return 0;
    }
  • 相关阅读:
    「日常训练」Single-use Stones (CFR476D2D)
    「日常训练」Greedy Arkady (CFR476D2C)
    「Haskell 学习」二 类型和函数(上)
    「学习记录」《数值分析》第二章计算实习题(Python语言)
    「日常训练」Alena And The Heater (CFR466D2D)
    Dubbo 消费者
    Dubbo 暴露服务
    Rpc
    git fail to push some refs....
    Spring Cloud (6)config 客户端配置 与GitHub通信
  • 原文地址:https://www.cnblogs.com/LYFmobai/p/10415583.html
Copyright © 2020-2023  润新知