• NOIP2017 跳房子(单调队列优化DP+二分)


    50分做法:

    可以发现答案具有单调性,所以二分答案。判断是否可行就需要DP。dp[i]表示到第i个格能得的最大值,从能跳向它的格进行转移即可。

    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    #include<cstdio>
    using namespace std;
    typedef long long ll;
    const int maxm=500007;
    int n,d,k;
    struct node
    {
     int x,z;
    }a[maxm];
    int ans=-1;
    ll dp[maxm];
    bool check(int x)
    {
      int maxx,minn;
      if(x<d)
      minn=d-x;
      else minn=1;
      maxx=d+x;
      memset(dp,-0x3f,sizeof(dp));
      dp[0]=0;
      for(int i=1;i<=n;i++)
      {
        for(int j=0;j<=i-1;j++)
        {
         if((a[i].x-a[j].x)<minn||(a[i].x-a[j].x)>maxx) continue;
    	 dp[i]=max(dp[i],dp[j]+a[j].z);	
        }
      }
      ll tot=-1e15;
      for(int i=0;i<=n;i++)
      {
         tot=max(tot,dp[i]);
      }
      if(tot>=k) return 1;
      else return 0;
    }
    int main()
    {
     scanf("%d%d%d",&n,&d,&k);
     for(int i=1;i<=n;i++)
     scanf("%d%d",&a[i].x,&a[i].z);
     int l=0,r=a[n].x;
     while(l<=r)
     {
      int mid=(l+r)>>1;
      if(check(mid))
      {
        ans=mid;
        r=mid-1;
      }
      else
      l=mid+1; 
     }
     printf("%d
    ",ans);
     return 0;
    }
    

    满分做法:

    50分做法的转移是O((nsqrt{n}))的,如何更快的转移呢?因为随着格的转移,能被跳到的区间也在转移,而且他一定是从这个区间中的最大值转移过来。

    嗯!单调队列即可。

    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    #include<cstdio>
    using namespace std;
    typedef long long ll;
    const int maxm=500007;
    int n,d,k;
    struct node
    {
     int x,z;
    }a[maxm];
    int ans=-1;
    ll dp[maxm];
    int q[maxm];
    bool check(int x)
    {
      int maxx,minn;
      if(x<d)
      minn=d-x;
      else minn=1;
      maxx=d+x;
      memset(dp,-0x3f,sizeof(dp));
      dp[0]=0;
      int j=0;
      int h=1,t=0;
      for(int i=1;i<=n;i++)
      {
        for(;a[j].x+minn<=a[i].x;j++)
        {
          while(h<=t&&dp[q[t]]<=dp[j]) t--;//维护一个单调递减的队列 
    	  q[++t]=j;	
        }
        while(h<=t&&a[q[h]].x+maxx<a[i].x) h++;
        if(h<=t) dp[i]=dp[q[h]]+a[i].z;
        if(dp[i]>=k) return 1;
      }
      return 0;
    }
    int main()
    {
     scanf("%d%d%d",&n,&d,&k);
     for(int i=1;i<=n;i++)
     scanf("%d%d",&a[i].x,&a[i].z);
     int l=0,r=a[n].x;
     while(l<=r)
     {
      int mid=(l+r)>>1;
      if(check(mid))
      {
        ans=mid;
        r=mid-1;
      }
      else
      l=mid+1; 
     }
     printf("%d
    ",ans);
     return 0;
    }
    
  • 相关阅读:
    SpringBoot2.x整合JDBC及初始化data.sql和schema.sql脚本
    CentOS7安装docker以及错误解决
    Maven的scope属性作用域范围
    (转)排序算法之简单选择排序
    系统开发博客专栏
    IDEA启动报错Plugin Error Problems found loading plugins的解决办法
    Promise函数的使用
    (转)排序算法之希尔排序
    .net Core AJAX使用Header传递参数,以JsonResult返回信息
    MVC 扩展RadioButtonListFor和CheckBoxListFor
  • 原文地址:https://www.cnblogs.com/lihan123/p/11687250.html
Copyright © 2020-2023  润新知