C. Pinkie Pie Eats Patty-cakes(二分)

Problem - C - Codeforces

C. Pinkie Pie Eats Patty-cakes(二分)_第1张图片

小粉饼买了一袋不同馅料的馅饼饼!但并不是所有的馅饼饼在馅料上都各不相同。换句话说,这个袋子里有一些馅料相同的馅饼。小粉派一个接一个地吃蛋糕。她喜欢玩,所以她决定不只是吃馅饼蛋糕,而是尽量不经常吃同样馅料的馅饼蛋糕。为了做到这一点,她希望吃到的馅料与吃到的馅料之间的最小距离尽可能大。在这里,小手指把两块馅饼之间的距离严格地称为它们之间吃的馅饼的数量。小粉派可以按任何顺序吃馅饼蛋糕。她没有耐心吃完所有的馅饼蛋糕,所以她让你帮她数一下在所有可能的吃顺序中,吃完的馅饼蛋糕与相同馅料之间的最大最小距离!小粉派打算多买几袋馅饼饼,所以她让你解决这个问题,买几袋!输入第一行包含一个整数T (1

Example

input

Copy

4
7
1 7 1 6 4 4 6
8
1 1 4 6 4 6 4 7
3
3 3 3
6
2 5 2 3 1 4

output

Copy

3
2
0
4

 请注意对于第一个袋子,Pinkie Pie可以按照以下顺序(按馅料)吃馅饼蛋糕:1,6,4,7,1,6,4(这样,最小距离等于3)。对于第二个袋子,Pinkie Pie可以按照以下顺序(按馅料)吃馅饼蛋糕:1,4,6,7,4,1,6,4(这样,最小距离等于2)。

题解:

看到最大最小就应该往二分上想了(好久没写二分了)

那如何check呢,我们check的应该是间隔为mid可不可以

举个例子:

1 1 1 1 2 2 2 2 3 4 5 6 7 8

1 2 (3 4) 1 2 (5 6) 1 2 (7 8) 2 6

1 1 1 2 2 2 3 3 3

123 123 123

看间隔为x,n - st + 1是否可以放下

st是出现数目从大往小第几个,因为前面已经放过一个大的了,肯定不能再放了,贪心来讲肯定是要先放大的

#include 
#include 
#include 
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef pair PII;
#define int long long
int cnt[100050];
bool cmp(int x,int y)
{
	return x > y;
}
int n;
int check(int x)
{
	int st = 1;
	for(int i = 1;i <= n&&cnt[i];i++)
	{
		int s = cnt[i];
		for(int j = st;j <= n&&s;j += (x + 1))
		{
			s--;
		} 
		if(s > 0)
		return 0;
		st++;
	}
	return 1;
}
void solve()
{
	memset(cnt,0,sizeof cnt);
	cin >> n;
	for(int i = 1;i <= n;i ++)
	{
		int x;
		cin >> x;
		cnt[x] ++;
	}
	sort(cnt + 1,cnt + 1+n,cmp);
	int l = 1,r = n;
	while(l <= r)
	{
		int mid = (l + r)/2;
		if(check(mid))
		{
			l = mid + 1;
		}
		else
		{
			r = mid - 1; 
		}
	}
	cout << l - 1 <<"\n";
}


signed main()
{
//	ios::sync_with_stdio(0);
//	cin.tie(0);cout.tie(0);
	int t = 1;
	cin >> t;
	while(t--)
	{
		solve(); 
	}
}

你可能感兴趣的:(算法)