大概思路:在样例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;
}