Codeforces Round #538 (Div. 2) B. Yet Another Array Partitioning Task

该博客介绍了一种算法,用于对输入数组进行排序,并找出最大的m*k个元素,然后根据这些元素构建满足条件的子序列。算法首先找出数组中最大的m*k个元素并计算它们的总和,接着在原始数组中遍历,寻找合适的元素划分子序列,直至满足每个子序列包含至少m个元素。整个过程涉及排序、计数和动态查找策略。
摘要由CSDN通过智能技术生成

大概思路:在样例1中,对输入的数组5,2,5,2,4,1,1,3,2 进行排序,找出最大的m*k(也就是6个)个元素5,5,4,3,2,2将这些元素的个数记录下来,记为map<int int >p。为什么是m*k个呢,原因在于每个子序列的要求是其中最大的m个元素相加,子序列一共有k个,那么最后肯定是输入数组中最大的m*k个元素相加求和。之后在输入数组中遍历,遇到一个符合的元素就p[int]--,减了两次就意味着找到了一个合适的分区,直接输出下标。

#include <bits/stdc++.h>
#define ll long long
#define x first
#define y second
const int maxn = 2e5 + 10;
using namespace std;
int a[maxn];//存放输入的数组
int b[maxn];//用于排序之后找到需要相加的数字
map<int, int >p;//之后用于标记
int main()
{
	int n, m, k;
	cin >> n >> m >> k;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];//两个数组都放一份
		b[i] = a[i];
	}
	sort(b + 1, b + 1 + n);//排序
	ll sum = 0;
	int t = b[n - m * k + 1];//找到最大的m*k个数字,求和就是答案
	for (int i = n; i >= n - m * k + 1; i--)
	{
		sum += b[i];
		p[b[i]]++;//这边标记m*k个数字中每个数字有多少个,map真甜蜜的好用
	}
	cout << sum << "\n";
	int indix = 1;
	for (int i = 1; i <= k - 1; i++)
	{
		int j = 0;
		for (; indix <= n; indix++)
		{
			if (a[indix] >= t && p[a[indix]] > 0)//序列内存在足够大的数字
			{
				j++;
				p[a[indix]]--;//将标记减一
			}
				
			if (j >= m)//划分出的子序列至少要m个数字
			{
				cout << indix << " ";
				indix++;//输出此时下标
				break;
			}
		}
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值