Educational Codeforces Round 55 (Rated for Div. 2):C. Multi-Subject Competition

C. Multi-Subject Competition

题目链接:https://codeforces.com/contest/1082/problem/C

题意:

给出n个信息,每个信息包含专业编号以及对应权值,先要求选出一些数量相等的专业(每种专业选的个数相等,不要求每种专业都要选),使对应权值最大。

题解:

一开始想的是枚举选的数量,然后再枚举每种专业从大到小贪心地选,但是时间超了...

其实还有更巧妙地方法,直接考虑每种专业选的个数从1到x对答案的贡献,用一个数组保存这一个贡献就好了。

对于一个专业对答案的贡献用到了最大连续子段和的技巧。

代码如下:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
int n,m;
vector <int> vec[N];
int main(){
    scanf("%d%d",&n,&m);
    int maxn = 0;
    int ans=0;
    for(int i=1;i<=n;i++){
        int s,r;
        scanf("%d%d",&s,&r);
        vec[s].push_back(r);
        int tmp=vec[s].size();
        maxn=max(maxn,tmp);
    }
    for(int i=1;i<=m;i++){
        sort(vec[i].begin(),vec[i].end());
        reverse(vec[i].begin(),vec[i].end());
    }
    int sum[N]={0};
    for(int i=1;i<=m;i++){
        int tot=0;
        int len=vec[i].size();
        for(int j=0;j<len;j++){
            tot+=vec[i][j];
            if(tot>0) sum[j+1]+=tot;
            else tot=0;
        }
    }
    for(int i=1;i<=maxn;i++) ans=max(ans,sum[i]);
    cout<<ans;
    return 0;
}
原文地址:https://www.cnblogs.com/heyuhhh/p/10056060.html