洛谷 3957 跳房子——二分答案+单调队列

题目:https://www.luogu.org/problemnew/show/P3957

二分答案以后可以dp求最优解,转移就是一个滑动窗口,所以用单调队列。

上午想好开 long long ,下午来了又忘了。到手的1A飞了。

但其实觉得很奇怪,因为一个 <k (<1e9)的数加一个s(<=1e5)怎么会爆 int ?

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=5e5+5;
int n,D,lm,x[N],c[N],ans=-1,q[N],he,tl;
ll dp[N];
int rdn()
{
  int ret=0;bool fx=1;char ch=getchar();
  while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
  while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
  return fx?ret:-ret;
}
bool solve(int l,int r)
{
  memset(dp,-2,sizeof dp); dp[0]=0;
  he=1;tl=0;q[0]=-1;
  for(int i=1;i<=n;i++)
    {
      while(x[i]-x[q[tl]+1]>=l)
    {
      int d=q[tl]+1;
      while(he<=tl&&dp[d]>dp[q[tl]])tl--;
      q[++tl]=d;
    }
      while(he<=tl&&x[i]-x[q[he]]>r)he++;
      if(he>tl)continue;
      dp[i]=dp[q[he]]+c[i];
      if(dp[i]>=lm)return true;
    }
  return false;
}
int main()
{
  n=rdn(); D=rdn(); lm=rdn();
  for(int i=1;i<=n;i++)x[i]=rdn(),c[i]=rdn();
  int l=0,r=max(D-1,x[n]-D);
  while(l<=r)
    {
      int mid=l+r>>1;
      if(solve(max(1,D-mid),D+mid))ans=mid,r=mid-1;
      else l=mid+1;
    }
  printf("%d\n",ans);
}

 

posted on 2018-10-27 16:51  Narh  阅读(116)  评论(0编辑  收藏  举报

导航