提供一种新思路(可能)
查看原帖
提供一种新思路(可能)
361676
Wch_1910231楼主2025/6/22 20:38

核心思想:贪心策略 + 动态维护分组

排序预处理: 首先对所有队员的实力值进行排序,使相同的数字相邻,连续的数字聚集 排序后可以方便地处理连续序列,同时避免重复数字问题

分组维护策略: 使用映射(map)维护每个组的结尾实力值和对应的组长度集合

每个结尾值对应一个最小堆(优先队列),存储所有以该值结尾的组长度

关键贪心原则:当有多个可选组时,总是选择长度最小的组进行扩展

遍历处理过程:

对于每个实力值 x:

检查是否存在以 x-1 结尾的组(即是否能扩展连续序列)

如果存在:

从最小堆中取出长度最小的组

将该组长度加1

更新到以 x 结尾的组中

如果不存在:

创建新组(长度为1)

放入以 x 结尾的组中

结果计算:

遍历所有组的长度

找到最小长度作为答案

贪心策略的正确性分析 平衡组长度:每次选择最小长度的组扩展,避免某些组过长而其他组过短

最大化最小值:通过保持组长度均衡,确保最小组尽可能大

处理重复值:相同数字会创建新组,避免违反组内无重复的规则

处理不连续:断层处自动创建新组,确保每组连续

时间复杂度分析 排序:O(nlogn)O(n \log n)

遍历 + 堆操作:每个元素最多一次入堆和出堆操作 O(logn)O(\log n)

总时间复杂度:O(nlogn)O(n \log n)

空间复杂度:O(n)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;
}

懒得看题解了,希望没重

2025/6/22 20:38
加载中...