Codeforces Round #809(div. 2) problem D

题目链接:

Problem - D1 - Codeforces

Problem - D2 - Codeforces

题意:

给定数组a,构造一个数组p,pi不超过k,使得:

达到最小值,求这个最小值。

两题仅数据量不同。

———————————————————————————————————————————

考虑最小值的范围肯定在0~a[0]之间,枚举最小值,让其他的尽量靠近最小值。每一个枚举最小值都可以得到一个拟定最优解,求这些解的最小值即可。

时间复杂度为O(t*n*n),可以过D1。

CODE:

#include<bits/stdc++.h>
using namespace std;
const int N=3010;
int a[N];
int main()
{
	int t;
	cin>>t;
	while(t--){
		int n,k;
		cin>>n>>k;
		for(int i=0;i<n;++i) cin>>a[i];
		int ans=INT_MAX;
		for(int i=0;i<=a[0];++i){
			int res=0,p;
			for(int j=0;j<n;++j){
				if(i) p=min(k,a[j]/i);
				else p=k;
				res=max(res,abs(a[j]/p-i));
			}
			ans=min(ans,res);
		}
		cout<<ans<<endl;
	}
	return 0;
}

对上述代码进行优化:题目保证a是增序列,还是枚举最小值,对循环第二层优化。如果最小值是0,答案可以直接求出。

对于非零最小值为i的情况,上一次是直接枚举整个序列求最大差值。现在我们枚举a[j]/i的可能值j,这样有限制条件j*i<=a[n-1],对于j=a[p]/i,a[p]=i*j,因此可以用二分查找的方式确定a[p]。

 CODE:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N],p[N];
int main()
{
	int t;
	cin>>t;
	while(t--){
		int n,k;
		cin>>n>>k;
		for(int i=0;i<n;++i) scanf("%d",&a[i]);
		int ans=INT_MAX;
		for(int i=0;i<=a[0];++i){
			int res=0,p;
			if(!i) res=a[n-1]/k;
			else{
				for(int j=1;1ll*j*i<=a[n-1];++j){
					p=lower_bound(a,a+n,i*(j+1))-a-1;
					if(p>=0&&a[p]/i==j) res=max(res,a[p]/min(k,a[p]/i)-i);
				}
			}
			ans=min(ans,res);
		}
		cout<<ans<<endl;
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值