几个小细节:
中途达到
k
k
k可以直接退出。
双端队列是先把后面的元素压进去,再把前面的弹出来,顺序不能反。
如果先弹再压,可能会导致后面不合要求的新压进来的没有弹掉。
#include<bits/stdc++.h>
#define cs const
#define re register
#define ll long long
#define fi first
#define se second
#define mp std::make_pair
#define pll std::pair<ll,ll>
cs int N=5e5+10;
cs ll oo=1e18;
ll dis[N],val[N],dp[N],d,k;
int n;
namespace IO{
cs int Rlen=1<<22|1;
char buf[Rlen],*p1,*p2;
inline char gc(){return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;}
template <typename T>
inline T get(){
char ch=gc();T x=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=gc();}
while(isdigit(ch)) x=((x+(x<<2))<<1)+(ch^48),ch=gc();
return x*f;
}
inline int gi(){return get<int>();}
inline ll gl(){return get<ll>();}
}
using IO::gi;
using IO::gl;
inline bool check(ll x){
ll mn=std::max(1ll,d-x),mx=d+x;
std::deque<pll> Q;dp[0]=0;
for(int re i=1;i<=n;++i) dp[i]=-oo;
for(int re i=1,j=0;i<=n;++i){
while(dis[j]<=dis[i]-mn){
while(!Q.empty()&&Q.back().fi<dp[j]) Q.pop_back();
Q.push_back(mp(dp[j],dis[j])),++j;
}while(!Q.empty()&&Q.front().se<(dis[i]-mx)) Q.pop_front();
dp[i]=(Q.empty()?-oo:Q.front().fi)+val[i];
if(dp[i]>=k) return true;
}return false;
}
int main(){
// freopen("2735.in","r",stdin);
n=gi(),d=gl(),k=gl();
for(int re i=1;i<=n;++i)
dis[i]=gl(),val[i]=gl();
ll l=0,r=dis[n],ans=oo;
while(l<=r){
ll mid=(l+r)>>1;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}printf("%lld\n",ans==oo?-1:ans);
}