跳房子
被普及组爆踩Orz
这个题的DP方程很显然,每次二分出g值,带入验证
如果
m
n
<
=
x
[
i
]
−
x
[
j
]
<
=
m
x
mn<=x[i]-x[j]<=mx
mn<=x[i]−x[j]<=mx,答案就可以进行转移:
f
[
i
]
=
m
a
x
(
f
[
j
]
+
s
[
i
]
)
f[i]=max(f[j]+s[i])
f[i]=max(f[j]+s[i])
由于任意时刻均可以结束游戏,需要每次判断一下是否
f
[
i
]
>
=
k
f[i]>=k
f[i]>=k,成立就不用继续DP
然后可以单调队列优化
代码:
80
p
t
s
(
没
加
单
调
队
列
)
80pts(没加单调队列)
80pts(没加单调队列)
#include<bits/stdc++.h>
using namespace std;
#define re register
#define ll long long
inline int rd(){
int re data=0,w=1;static char ch=0;ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(isdigit(ch))data=(data<<1)+(data<<3)+(ch^48),ch=getchar();
return data*w;
}
const int N=500005;
bool flag;int n,d,s[N],l=1,r,mid,x[N],ans=INT_MAX,q[N],head,tail;ll now,f[N],k;
inline bool check(int mn,int mx){
memset(f,0xb3,sizeof(f)),now=f[0]=0,q[head=tail=1]=0;
for(int re i=1;i<=n;++i){
for(int re j=i-1;j>=0;--j){
if(x[i]-x[j]<mn)continue;
if(x[i]-x[j]>mx)break;
f[i]=max(f[i],f[j]+s[i]);
}now=max(f[i],now);
if(now>=k)return 1;
}
return 0;
}
signed main(){
n=rd(),d=rd(),k=rd();
for(int re i=1;i<=n;++i)x[i]=rd(),s[i]=rd();r=1e9;
if(!check(1,x[n]))puts("-1"),exit(0);
while(l+1<r){
mid=l+r>>1;
if(check(max(d-mid,1),d+mid))ans=min(ans,mid),r=mid;
else l=mid+1;
}if(check(max(d-l,1),d+l))printf("%d",l);else if(check(max(d-mid,1),d+mid))printf("%d",mid);else printf("%d",r);
exit(0);
}
100 p t s 100pts 100pts
#include<cstdio>
#include<iostream>
using namespace std;
#define re register
#define ll long long
#define inf 0x4f4f4f4f
inline char nc(){
static char buf[10000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,10000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd(){
int re data=0,w=1;static char ch=0;ch=nc();
while(!isdigit(ch)&&ch!='-')ch=nc();
if(ch=='-')w=-1,ch=nc();
while(isdigit(ch))data=(data<<1)+(data<<3)+(ch^48),ch=nc();
return data*w;
}
const int N=500005;
bool flag;int n,d,s[N],l=1,r,mid,x[N],ans=inf,q[N],head,tail;ll f[N],k;
inline bool check(int mn,int mx,int j=0){
f[0]=0,q[head=1]=0,tail=0;
for(int re i=1;i<=n;++i){
while(x[i]-x[j]>=mn&&j<i){
if(f[j]!=-inf){while(head<=tail&&f[q[tail]]<=f[j])--tail;q[++tail]=j;}
++j;
}
while(head<=tail&&x[i]-x[q[head]]>mx)++head;
if(head<=tail)f[i]=f[q[head]]+s[i];
else f[i]=-inf;
if(f[i]>=k)return 1;
}
return 0;
}
signed main(){
n=rd(),d=rd(),k=rd();
for(int re i=1;i<=n;++i)x[i]=rd(),s[i]=rd();r=x[n];
if(!check(1,x[n])){puts("-1");return 0;}
while(l<=r){
mid=l+r>>1;
if(check(max(d-mid,1),d+mid))ans=min(ans,mid),r=mid-1;
else l=mid+1;
}printf("%d",ans);
}