【题解】Luogu P3957 跳房子 二分
基本算法1-3
NOip 2017 普及 T4
Update:感谢Jackpei神仙指出我的辣鸡错误(没开long long我就是个傻子
发现如果花$x$的金币能使机器人在$[l,r]$区间内跳跃,那花$x+c$的金币一定也能
二分花多少钱能使机器人得到$k$分
设f[i]表示跳到第$i$格的最高分,每次dp
没有用单调队列的辣鸡做法
1 #include <bits/stdc++.h> 2 using namespace std; 3 namespace gengyf{ 4 #define int long long 5 const int maxn=5e5+10; 6 const int mod=1e9; 7 inline int read(){ 8 int f=1,x=0;char s=getchar(); 9 while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} 10 while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} 11 return f*x; 12 } 13 int n,d,k,sum,f[maxn],ans; 14 struct node{ 15 int pos,val; 16 }a[maxn]; 17 bool check(int x){ 18 int l=max(d-x,1LL),r=d+x; 19 memset(f,-127,sizeof(f)); 20 f[0]=0; 21 for(int i=1;i<=n;i++) 22 for(int j=i-1;j>=0;j--){ 23 int p=a[i].pos-a[j].pos; 24 if(p<l)continue; 25 if(p>r)break; 26 f[i]=max(f[i],f[j]+a[i].val); 27 if(f[i]>=k)return 1; 28 } 29 return 0; 30 } 31 int main(){ 32 n=read();d=read();k=read(); 33 for(int i=1;i<=n;i++){ 34 a[i].pos=read();a[i].val=read(); 35 sum=max(sum,sum+a[i].val); 36 } 37 if(sum<k){ 38 puts("-1");return 0; 39 } 40 int l=0,r=maxn; 41 while(l<=r){ 42 int mid=(l+r)>>1; 43 if(check(mid)){ 44 ans=mid;r=mid-1; 45 } 46 else l=mid+1; 47 } 48 printf("%lld",ans); 49 return 0; 50 } 51 } 52 signed main(){ 53 gengyf::main(); 54 return 0; 55 }