zoukankan      html  css  js  c++  java
  • 「CF1342D Multiple Testcases」

    题目大意

    给出一个序列,和一些限制,需要将这个序列分到最少的组中使得每个组中大于 (i) 的数小于等于 (c_i) 个.

    分析

    先计算最小的组数考虑计算 (sum_i=sum_{i=j}^{n}(a_jgeq i)),计算过程类似一个后缀和,那么就可以直接计算出大于等于 (i) 的数至少要放在几组中,然后取max就好了.

    然后考虑怎么去放,很显然是按顺序去放(从小到大排序后依次轮流放入)最优,可以保证一定满足,具体证明可以理解一下计算公式.

    排序如果用桶排可以做到 (mathcal{O}(n+k)),但是我比较懒,就直接用了 sort.

    代码

    #include<bits/stdc++.h>
    #define REP(i,first,last) for(int i=first;i<=last;++i)
    #define DOW(i,first,last) for(int i=first;i>=last;--i)
    using namespace std;
    const int MAXN=2e5+5;
    int n,k;
    int arr[MAXN];
    int c[MAXN];
    int sum[MAXN];
    int main()
    {
    	scanf("%d%d",&n,&k);
    	REP(i,1,n)
    	{
    		scanf("%d",&arr[i]);
    		sum[arr[i]]++;//统计出现次数
    	}
    	DOW(i,k-1,1)//后缀和
    	{
    		sum[i]+=sum[i+1];
    	}
    	int answer=0;
    	sort(arr+1,arr+1+n);
    	REP(i,1,k)
    	{
    		scanf("%d",&c[i]);
    	}
    	REP(i,1,k)
    	{
    		answer=max(answer,sum[i]/c[i]+(bool)(sum[i]%c[i]));//计算最小组数
    	}
    	printf("%d
    ",answer);
    	REP(i,1,answer)
    	{
    		int now=i,p=0;
    		while(now<=n)//考虑是按组数循环,先计算出个数再输出
    		{
    			++p;
    			now+=answer;
    		}
    		printf("%d ",p);
    		now=i;
    		while(now<=n)
    		{
    			printf("%d ",arr[now]);
    			now+=answer;
    		}
    		printf("
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    java设计模式之适配器模式
    在Eclipse中建立Maven Web项目
    java设计模式之原型模式
    java设计模式之建造者模式
    java设计模式之工厂模式
    java设计模式之单例模式
    C# 前端多次上传文件
    C# async 和 await
    .NET 4.0 任务(Task)
    C# 5.0
  • 原文地址:https://www.cnblogs.com/Sxy_Limit/p/12822234.html
Copyright © 2011-2022 走看看