【分治】洛谷月赛

链接

洛谷月赛

题目描述

在这里插入图片描述

思路

答案必然是最大数的某个约数,那就从大到小枚举
然后看能否分成大于等于k块
判断考虑分治
对于一个区间最大值x,如果它是约数的倍数,那么就直接考虑左右分
如果本身不是,那就考虑找一个左右分块合并进去

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;

const int N = 1e6 + 100,M = 1010;
int n, m, pl, maxn, k, a[N], s[N];
int find(int l,int r)
{
    
    
	int pl=0,maxn=0;
	for(int i = l; i <= r; ++i) if(a[i] > maxn) maxn = a[i], pl = i;
	return pl; 
}
int pd(int l, int r, int num)
{
    
    
	if(l > r) return 0;
	int pl = find(l, r);
	if(a[pl] % num == 0 ) return pd(l, pl - 1, num) + pd(pl + 1, r, num) + 1;
	if(l == 1) return pd(l, pl - 1, num );
	if(r == n) return pd(pl + 1, r, num );
	return max(pd(l, pl - 1,num), pd(pl + 1, r, num));
}

int main ()
{
    
    
	scanf("%d%d", &n, &k );
	for(int i = 1; i <= n; ++i ) scanf("%d", &a[i]), maxn = max(maxn, a[i]);
	for(int i = 1; i <= maxn / i; ++i )
	{
    
    
		if(i * i == maxn) s[++m] = i;
		else if(maxn % i == 0 ) s[++m] = i, s[++m] = maxn / i;
	}
	sort(s + 1,s + 1 + m );
	for(int i = m; i >= 1; --i ) 
	if(pd(1, n, s[i]) >= k) 
	{
    
    
		printf ( "%d",s[i] );
		break;
	}
	return 0;
}

おすすめ

転載: blog.csdn.net/LTH060226/article/details/119810955