首页 > 其他 > 详细

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

时间:2019-10-16 19:39:45      阅读:77      评论:0      收藏:0      [点我收藏+]

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\n",ans);
 return 0;
}

满分做法:

50分做法的转移是O(\(n\sqrt{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\n",ans);
 return 0;
}

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

原文:https://www.cnblogs.com/lihan123/p/11687250.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!