• [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 }
  • 相关阅读:
    Java Character类
    JavaMath&Number类
    oracle中创建数据库实例
    Jenkins安装和配置
    crontab计划 -计划任务和日志管理
    centos修改默认字符编码为GBK(服务器端java GBK字符乱码)
    使用vsphere client 克隆虚拟机
    建索引让SQL飞起来
    oracle中对LONG列进行查询
    优化sql,返回行数少情况下,NL比hash快好多
  • 原文地址:https://www.cnblogs.com/skylee03/p/8644844.html
走看看 - 开发者的网上家园