codeforces538B.Yet Another Array Partitioning Task

An array b is called to be a subarray of a if it forms a continuous subsequence of a, that is, if it is equal to al, al+1, …, ar for some l,r.

Suppose m is some known constant. For any array, having m or more elements, let’s define it’s beauty as the sum of m largest elements of that array. For example:

For array x=[4,3,1,5,2] and m=3, the 3 largest elements of x are 5, 4 and 3, so the beauty of x is 5+4+3=12.
For array x=[10,10,10] and m=2, the beauty of x is 10+10=20.

You are given an array a1,a2,…,an, the value of the said constant m and an integer k. Your need to split the array a into exactly k subarrays such that:Each element from a belongs to exactly one subarray.Each subarray has at least m elements.The sum of all beauties of k subarrays is maximum possible.

Input

The first line contains three integers n, m and k (2≤n≤2⋅105, 1≤m, 2≤k, m⋅k≤n) — the number of elements in a, the constant m in the definition of beauty and the number of subarrays to split to.
The second line contains n
integers a1,a2,…,an (−1e9≤ai≤1e9 ).

Output
In the first line, print the maximum possible sum of the beauties of the subarrays in the optimal partition.
In the second line, print k−1 integers p1,p2,…,pk−1 (1≤p1<p2<…<pk−1<n) representing the partition of the array, in which:
All elements with indices from 1to p1 belong to the first subarray.
All elements with indices from p1+1 to p2 belong to the second subarray.
All elements with indices from pk−1+1 to n belong to the last, k-th subarray.

If there are several optimal partitions, print any of them.

Examples
Input

9 2 3
5 2 5 2 4 1 1 3 2

Output

21
3 5 

Input

6 1 4
4 1 3 2 2 3

Output

12
1 3 5 

Input

2 1 2
-1000000000 1000000000

Output

0
1 

给出一个数组,将这个数组分成k个子数组,将这k个子数组的前m大个数的和记为一个中间量,现求这k个子数组中间量的和的最大值。
根据题意,也许会有一个模糊的判断:和的最大值要求每一个中间量尽可能的大,而每一个中间量尽可能大又要求这个子数组中前m个元素尽可能的大,所以可能会有这样一个感觉上的判断:遍历数组,将尽可能大的元素划分为一个区间。
但这并不足以构成一个完整的判断标准,还需要一个具体的方式去判定这个数是否足够大。
不难的得知,这个和的极大值就是数组中前m*k大个元素的和,可以此作为划分依据 :将原数组划分为k个子数组,每一个子数组中前m大个元素都在这个数组前m *k大个元素中,进而将问题转化为将 m * k个元素划分为k组。
而处理这个问题,可以先将这些元素在原数组中的位置进行标记,再遍历数组统计标记的个数。因为这些元素一定比其他位置上的元素要大,故可以保证这样划分出来的子数组中前m大元素一定是原数组中前m * k大中元素。


#include <stdio.h>
#include <climits>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <utility>
#include <vector>
#include <string>
#define INF 0x3f3f3f3f
#define ll long long
#define re return
#define Pair pair<int,int>
#define Make(a,b) make_pair(a,b)
#define Push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;
struct Record{
    int val;
    int index;
};

vector<int> index;
bool pushIn[200024];
Record store[200024];
inline bool mmp(const Record& a,const Record& b);
int main(){
    ios::sync_with_stdio(false);

    int n,m,k;
    cin>>n>>m>>k;
    rep(i,1,n+1){
        cin>>store[i].val;
        store[i].index=i;
        pushIn[i]=false;
    }

    sort(store+1,store+1+n,mmp);
    ll sum=0;
    rep(i,1,m*k+1){
        sum+=store[i].val;
        pushIn[store[i].index]=true;
    }

    int cou=0;
    rep(i,1,n+1){
        if(pushIn[i]){
            cou++;
            if(cou==m){
                cou=0;
                index.Push(i);
            }
        }
    }

    cout<<sum<<endl;
    rep(i,0,k-1)
        cout<<index[i]<<" ";
    cout<<endl;
    re 0;
}
inline bool mmp(const Record& a,const Record& b){
    re a.val>b.val;
}

猜你喜欢

转载自blog.csdn.net/white_156/article/details/87539809