核心思想:贪心策略 + 动态维护分组
排序预处理: 首先对所有队员的实力值进行排序,使相同的数字相邻,连续的数字聚集 排序后可以方便地处理连续序列,同时避免重复数字问题
分组维护策略: 使用映射(map)维护每个组的结尾实力值和对应的组长度集合
每个结尾值对应一个最小堆(优先队列),存储所有以该值结尾的组长度
关键贪心原则:当有多个可选组时,总是选择长度最小的组进行扩展
遍历处理过程:
对于每个实力值 x:
检查是否存在以 x-1 结尾的组(即是否能扩展连续序列)
如果存在:
从最小堆中取出长度最小的组
将该组长度加1
更新到以 x 结尾的组中
如果不存在:
创建新组(长度为1)
放入以 x 结尾的组中
结果计算:
遍历所有组的长度
找到最小长度作为答案
贪心策略的正确性分析 平衡组长度:每次选择最小长度的组扩展,避免某些组过长而其他组过短
最大化最小值:通过保持组长度均衡,确保最小组尽可能大
处理重复值:相同数字会创建新组,避免违反组内无重复的规则
处理不连续:断层处自动创建新组,确保每组连续
时间复杂度分析 排序:O(nlogn)
遍历 + 堆操作:每个元素最多一次入堆和出堆操作 O(logn)
总时间复杂度:O(nlogn)
空间复杂度:O(n)
#include<bits/stdc++.h>
using namespace std;
int n,ans=INT_MAX,a[100005];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
sort(a+1,a+n+1);
map<int,priority_queue<int,vector<int>,greater<int> > > tail_group;
for(int i=1;i<=n;i++)
{
int x=a[i];
if(tail_group.find(x-1)!=tail_group.end()&&!tail_group[x-1].empty())
{
int min_len=tail_group[x-1].top();
tail_group[x-1].pop();
tail_group[x].push(min_len+1);
}
else tail_group[x].push(1);
}
for(auto& p:tail_group)
{
auto& pq=p.second;
while(!pq.empty())
{
ans=min(ans,pq.top());
pq.pop();
}
}
printf("%d",ans);
return 0;
}
懒得看题解了,希望没重