【题解】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 }
View Code

 

posted @ 2019-10-18 10:28  喵の耳  阅读(130)  评论(0编辑  收藏  举报