P3957 [NOIP2017 普及组] 跳房子
思路:
首先发现单调性,灵活性增加
那么可以二分求
考虑动态规划求得能走到的最大分数,令
可以使用单调队列维护:
-
若当前队尾为
,且 ,则这个 无法对 造成贡献,直接不断弹出即可。 -
若当前队头为
,且 ,则这个 可以对 造成贡献,不断插入即可。 -
因为要维护最大值,可以使用单调队列。
时间复杂度为
完整代码:
#include<bits/stdc++.h> #define Add(x,y) (x+y>=mod)?(x+y-mod):(x+y) #define lowbit(x) x&(-x) #define pi pair<ll,ll> #define pii pair<ll,pair<ll,ll>> #define iip pair<pair<ll,ll>,ll> #define ppii pair<pair<ll,ll>,pair<ll,ll>> #define fi first #define se second #define full(l,r,x) for(auto it=l;it!=r;it++) (*it)=x #define Full(a) memset(a,0,sizeof(a)) #define open(s1,s2) freopen(s1,"r",stdin),freopen(s2,"w",stdout); using namespace std; typedef double db; typedef unsigned long long ull; typedef long long ll; bool Begin; const ll N=5e5+10; inline ll read(){ ll x=0,f=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9'){ x=(x<<1)+(x<<3)+(c^48); c=getchar(); } return x*f; } inline void write(ll x){ if(x<0){ putchar('-'); x=-x; } if(x>9) write(x/10); putchar(x%10+'0'); } ll n,d,k,l,r,head,tail,ans=-1; ll a[N],b[N],dp[N],Q[N]; ll check(ll l,ll r){ head=1,tail=0; ll sum=0,x=1,y=0; for(int i=1;i<=n+1;i++){ if(i>1) dp[i]=-1e18; while(a[y+1]<=a[i]-l&&y<=n){ y++; while(dp[y]>dp[Q[tail]]&&tail>=head) tail--; if(dp[y]>=-1e18) Q[++tail]=y; } while(a[x]<a[i]-r&&x<=n){ if(Q[head]==x) head++; x++; } if(tail>=head) dp[i]=b[i]+dp[Q[head]]; sum=max(sum,dp[i]); } return sum; } bool End; int main(){ // open("A.in","A.out"); n=read(),d=read(),k=read(); for(int i=1;i<=n;i++){ a[i+1]=read(); b[i+1]=read(); } l=0,r=1e9; while(l<=r){ ll mid=(l+r)>>1; if(check(max(d-mid,1ll),d+mid)>=k){ r=mid-1; ans=mid; } else l=mid+1; } write(ans); cerr<<'\n'<<abs(&Begin-&End)/1048576<<"MB"; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步