Codeforces(D. Multiple Testcases)后缀和

在这里插入图片描述
在这里插入图片描述

大题题意:给你一个数组m和c,要将m数组划分成若干个子数组,c[i]表示每个子数组中最多有c[i]个大于等于 i 的。问最小能划分成几组并输出每个组。

开一个sum数组保存后缀和,sum[i]表示大于等于 i 的数有多少个,然后针对每个 i ,需要分sum[i]/c[i](上取整)个组,确定好分多少组直接分就好了

代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;

ll m[200005],c[200005];
ll sum[200005],book[200005];
vector<ll>d[200005];
int main()
{
    
    
    ll n,k;
    scanf("%lld %lld",&n,&k);
    for(int i=1;i<=n;i++)
    {
    
    scanf("%lld",&m[i]);book[m[i]]++;}
    for(int i=1;i<=k;i++)
    {
    
    scanf("%lld",&c[i]);}
    sort(m+1,m+1+n);
    for(int i=200001;i>=1;i--)
    {
    
    
        if(book[i]>0)
        {
    
    sum[i]=sum[i+1]+book[i];}
        else
        {
    
    sum[i]=sum[i+1];}
    }
    ll maxx=-1,op;
    for(int i=1;i<=k;i++)
    {
    
    
        if(c[i]>=sum[i])
        {
    
    
            op=1;
            maxx=max(op,maxx);
        }
        else
        {
    
    
            if(sum[i]%c[i]==0)
            {
    
    
                op=sum[i]/c[i];
                maxx=max(maxx,op);
            }
            if(sum[i]%c[i]!=0)
            {
    
    
                op=sum[i]/c[i]+1;
                maxx=max(maxx,op);
            }
        }
    }
    printf("%lld\n",maxx);
    int e=1;
    for(int i=n;i>=1;i--)
    {
    
    
        d[e].push_back(m[i]);
        e++;
        if(e==maxx+1)
        {
    
    e=1;}
    }
    for(int i=1;i<=maxx;i++)
    {
    
    
        printf("%lld ",d[i].size());
        for(int j=0;j<d[i].size();j++)
        {
    
    printf("%lld ",d[i][j]);}
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43781431/article/details/105799646