zoukankan      html  css  js  c++  java
  • Little Bird(BZOJ 3831)

    题目大意:

    有一排n棵树,第i棵树的高度是Di。
    MHY要从第一棵树到第n棵树去找他的妹子玩。
    如果MHY在第i棵树,那么他可以跳到第i+1,i+2,...,i+k棵树。
    如果MHY跳到一棵不矮于当前树的树,那么他的劳累值会+1,否则不会。
    为了有体力和妹子玩,MHY要最小化劳累值。
    输入:第一行一个n,代表树的个数,接下来一行n个数,代表每棵树的高度,接下来一个数Q,代表Q次询问,最后Q行数,代表每次询问的k。
    /*
      依据题目,很容易得到DP方程 f[i]=f[j]+(f[j]<=f[i]) (j+k>=i)
      但是复杂度为0(n^2),显然超时,所以应该采用优先队列优化。
      优化:
        设定优先队列是以f值递减的顺序排列,可以保证更新i的时候用队头元素最优 
    */
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define M 1000010
    using namespace std;
    int n,k,q[M],high[M],f[M];
    int can(int a,int b)
    {
        if(f[a]>f[b])return 1;
        if(f[a]==f[b]&&high[a]<=high[b])return 1;
        return 0;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
          scanf("%d",&high[i]);
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int head=1,tail=1;
            q[1]=1;
            f[1]=0;
            scanf("%d",&k);
            for(int i=2;i<=n;i++)
            {
                while(head<tail&&q[head]+k<i)head++;//把距离不满足条件的删去 
                f[i]=f[q[head]]+(high[q[head]]<=high[i]);//更新 
                while(head<tail&&can(q[tail],i))//将队列按优先值更新 
                  tail--;
                q[++tail]=i;//加入新元素 
            }
            printf("%d
    ",f[n]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    算法竞赛入门经典习题2-3 韩信点兵
    ios入门之c语言篇——基本函数——5——素数判断
    ios入门之c语言篇——基本函数——4——数值交换函数
    144. Binary Tree Preorder Traversal
    143. Reorder List
    142. Linked List Cycle II
    139. Word Break
    138. Copy List with Random Pointer
    137. Single Number II
    135. Candy
  • 原文地址:https://www.cnblogs.com/harden/p/5705098.html
Copyright © 2011-2022 走看看