CF1114B Yet Another Array Partitioning Task(贪心,构造题)

我至今不敢相信我被这么一道简单的题卡了这么久……看来还是太弱了……

题目链接:CF原网

题目大意:定义一个序列的“美丽度”为这个序列前 $m$ 大的数的和。现在有一个长度为 $n$ 的序列,你需要把它分成 $k$ 个长度至少为 $m$ 的连续子序列,每个元素不重不漏,使得这些子串的“美丽度”之和最大。而且要求输出划分方案。

$1\le n\le 2\times 10^5,m\ge 1,k\ge 2,m\times k\le n$。


贪心地想,最后的划分方案中,计入总和的数,应该是原序列中前 $m\times k$ 大的数。如果有相同的数,随便选都行。

把这 $m\times k$ 个数标记一下。

那么究竟可不可以做到呢?其实很简单,从第一个还未被分配的数开始选,不断往后推,如果当前已经有了 $m$ 个数,那么这一段就是答案的一个子序列。

时间复杂度 $O(n\log n)$。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=;
#define MP make_pair
#define PB push_back
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
char ch=getchar();int x=,f=;
while(ch<'' || ch>'') f|=ch=='-',ch=getchar();
while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
return f?-x:x;
}
int n,m,k;
bool tag[maxn];
ll ans;
struct node{
int val,id;
bool operator<(const node &nd)const{
if(val!=nd.val) return val>nd.val;
return id<nd.id;
}
}nd[maxn];
int main(){
n=read();m=read();k=read();
FOR(i,,n) nd[i].val=read(),nd[i].id=i;
sort(nd+,nd+n+);
FOR(i,,m*k) ans+=nd[i].val,tag[nd[i].id]=true; //累加答案,标记
printf("%lld\n",ans);
int tot=;
FOR(i,,n){
int cnt=,j=i; //从还未分配的开始
while(j<=n && cnt<m){ //还不足m个
if(tag[j]) cnt++;
j++;
}
i=j-; //注意-1
if(tot<k) printf("%d ",i),tot++;
}
}
上一篇:Struts2(十二)使用验证框架验证数据较验


下一篇:截图工具(window 10 和Mac OSX)