• 题解 P3957 【跳房子】


    对于这题有一个不用单调队列并且不是玄学设置区间最大值的做法

    这题校内模拟考的时候打二分+枚举,结果写炸了,跑过来看题解发现为什么他们的区间最大值都是 $ 1005 $ ???特别懵,其实我的代码在dp方面并没有改善仍然是 $ O(n^2) $ 但在对区间最大值依照题意进行缩小从而可以 $ AC $。

    首先我们能不去走负数的格子就尽量不去走负数的格子,这样就可以保证得分最高,但也会导致改造费用升高或不升(但最大值一定在此)那么我们考虑如何去只走正数格子,我们看到当 $ g >= d $ 的时候每次最多跳 $ g+d $ 格那么如果我们保证 $ g=max(d,max( $ 相邻两个正数格子间的距离 $ )) $ 那么我们就可以保证一定能走到所有正数格子,那么我们就可以以此缩小二分的区间从而缩小时间复杂度啦!

    第一个是 $ r=1005 $ 另外一个就是按照前面的方法计算的,要快一点点qwq

    对于 $ dp $ 楼下的大佬讲得挺详细的,我这个蒟蒻就不详细阐述了吧

    代码君

    #include<bits/stdc++.h>
    using namespace std;
    const int size=500005;
    struct node{
    	long long data;
    	long long dis;
    }a[size];
    long long dp[size],di;
    int n,d,k;
    bool cheak(int g){
    	memset(dp,-127,sizeof(dp));
    	dp[0]=0;
    	for(int i=1;i<=n;++i){
    		for(int j=i-1;j>=0;--j){
    			 if(a[i].dis-a[j].dis<max(1,d-g)) continue;
    			 if(a[i].dis-a[j].dis>d+g) break;
    			 dp[i]=max(dp[i],dp[j]+a[i].data);
    			 if(dp[i]>=k) return true;
    		}
    	}
    	return false;
    }
    int main(){
    	scanf("%d %d %d",&n,&d,&k);
    	int tmp=0;
    	for(int i=1;i<=n;++i){
    		scanf("%lld %lld",&a[i].dis,&a[i].data);
    		if(a[i].data>0) di=max(di,a[i].dis-a[tmp].dis),tmp=i;
    	} 
    	int l=0,r=max(di,(long long)d),ans=1<<30;
    	while(l<=r){
    		int mid=(l+r)>>1;
    		if(cheak(mid)){
    			r=mid-1;
    			ans=min(mid,ans);
    		}else l=mid+1;
    	}if(ans==1<<30) ans=-1;
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    UWP开发必备:常用数据列表控件汇总比较
    CodeForces 372 A. Counting Kangaroos is Fun
    ubuntu 13.10 eclipse 菜单栏不可用的问题
    Codeforces Round #219(Div. 2)373 B. Making Sequences is Fun(二分+找规律)
    Git/Github使用方法小记
    Ubuntu 下jdk的安装
    VIM简明教程
    codeforces 371 C-Hamburgers
    codeforces 371A K-Periodic Array
    计算机网络中IP地址和MAC地址
  • 原文地址:https://www.cnblogs.com/donkey2603089141/p/11789204.html
Copyright © 2020-2023  润新知