zoukankan      html  css  js  c++  java
  • [POI2014]Little Bird

    题目大意:
      $n(nle10^6)$个点排成一排,每个点有一个高度$h_i$,现在要从$1$号点跳到$n$号点,从$i$号点出发跳到的点$j$满足$i<jle i+k$,若$h_jge h_i$则增加$1$的代价。给出$q(qle25)$组询问,对于每次给出的$k$,求从$1$跳到$n$的最小代价。

    思路:
      用$f_i$表示从$1$跳到$i$的最小代价,则一个显然的状态转移方程为$f_i=min{f_j+[h_ige h_j]}$。然而这样是$O(n^2q)$的,显然会TLE。
      考虑队列优化。若当前要加入队列的点是$i$,队尾元素为$j$。若$f_i<f_j$或$j_i=f_j$且$h_i>=h_j$,用$i$转移一定更优,将$j$出队​。转移时将超过$k$范围内的元素出队,每次用队首元素转移即可。时间复杂度$O(nq)$。

     1 #include<queue>
     2 #include<cstdio>
     3 #include<cctype>
     4 #include<climits>
     5 inline int getint() {
     6     register char ch;
     7     while(!isdigit(ch=getchar()));
     8     register int x=ch^'0';
     9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    10     return x;
    11 }
    12 const int N=1e6+1;
    13 int h[N],f[N];
    14 std::deque<int> q;
    15 int main() {
    16     const int n=getint();
    17     for(register int i=1;i<=n;i++) h[i]=getint();
    18     for(register int m=getint();m;m--) {
    19         const int k=getint();
    20         q.clear();
    21         q.push_back(1);
    22         for(register int i=2;i<=n;i++) {
    23             while(!q.empty()&&i-q.front()>k) q.pop_front();
    24             f[i]=f[q.front()]+(h[i]>=h[q.front()]);
    25             while(!q.empty()&&(f[q.back()]>f[i]||(f[q.back()]==f[i]&&h[q.back()]<=h[i]))) q.pop_back();
    26             q.push_back(i);
    27         }
    28         printf("%d
    ",f[n]);
    29     }
    30     return 0;
    31 }
  • 相关阅读:
    OPENSSH 详解
    红帽RHEL8和7有什么区别(Centos8与7参照redhat)
    RHEL8和CentOS8怎么重启网络
    Redhat7.x Openssh、Openssl升级
    RHEL7.x更换更换Centos yum源
    NTP时间同步
    2019-12-17:权限维持,笔记
    2019-12-13:提权学习,笔记
    2019-12-11:kali linux工具Msfvenom 命令自动补全
    2019-12-10:win7,win12提权练习
  • 原文地址:https://www.cnblogs.com/skylee03/p/8644844.html
Copyright © 2011-2022 走看看