NOIP2017 跳房子

传送门

几个小细节:
中途达到 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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值