跳房子
题目
解析
显而易见,首先二分答案,每次裸DP一下,求上下界即可
因为裸DP是O(n2)的,再加个log,2s时限+氧气也救不回来
考虑优化DP,显而易见单调队列,注意这里踢的条件以x的差值为界限
快读快输已成日常
code:
#include<cstring>
#include<cstdio>
#define int long long
using namespace std;
inline int max(int x,int y){
}
inline bool idigit(char x){
return (x<'0'|x>'9')?0:1;}
inline int read()
{
int num=0,f=1;
char c=0;
while(!idigit(c=getchar())){
if(c=='-')f=-1;}
while(idigit(c))num=(num<<1)+(num<<3)+(c&15),c=getchar();
return num*f;
}
inline void write(int x)
{
int F[20];
int tmp=x>0?x:-x;
if(x<0)putchar('-');
int cnt=0;
while(tmp>0){
F[cnt++]=tmp%10+'0';tmp/=10;}
while(cnt>0)putchar(F[--cnt]);
if(x==0)putchar('0');
putchar('\n');
}
int n,d,g,dp[500010],p,q,L=0,R,mid,x[500010],ans=1e18,s[500010],la,b[500010],l,r;
bool check(int y)
{
p=max(d-y,1),q=d+y,la=1,l=1,r=1,b[1]=0;
for(int i=1;i<=n;++i)
{
while(l<r&&x[i]-x[b[l]]>q)++l;
if(x[i]-x[b[l]]<=q&&x[i]-x[b[l]]>=p){
dp[i]=dp[b[l]]+s[i];if(dp[i]>=g)return 1;}
else dp[i]=-4e17;
while(la<=i&&x[i+1]-x[la]>=p)
{
while(l<=r&&dp[b[r]]<=dp[la])--r;
b[++r]=la,++la;
}
}
return 0;
}
signed main()
{
n=read(),d=read(),g=read();
for(int i=1;i<=n;++i)x[i]=read(),s[i]=read();
R=1e9;
while(L<=R)
{
mid=(L+R)>>1;
if(check(mid))R=mid-1,ans=(ans>mid)?mid:ans;
else L=mid+1;
}//注意二分条件,保证ans是可行解
if(ans==1e18)printf("-1");
else write(ans);
return 0;
}