暴力搜索-1082c-Multi-Subject Competition(cf)

原题

C. Multi-Subject Competition

time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

A multi-subject competition is coming! The competition has mm different subjects participants can choose from. That's why Alex (the coach) should form a competition delegation among his students.

He has nn candidates. For the ii-th person he knows subject sisi the candidate specializes in and riri — a skill level in his specialization (this level can be negative!).

The rules of the competition require each delegation to choose some subset of subjects they will participate in. The only restriction is that the number of students from the team participating in each of the chosen subjects should be the same.

Alex decided that each candidate would participate only in the subject he specializes in. Now Alex wonders whom he has to choose to maximize the total sum of skill levels of all delegates, or just skip the competition this year if every valid non-empty delegation has negative sum.

(Of course, Alex doesn't have any spare money so each delegate he chooses must participate in the competition).

Input

The first line contains two integers nn and mm (1n10^5 1m10^5) — the number of candidates and the number of subjects.

The next nn lines contains two integers per line: sisi and riri (1sim10^4ri10^4) — the subject of specialization and the skill level of the ii-th candidate.

Output

Print the single integer — the maximum total sum of skills of delegates who form a valid delegation (according to rules above) or 00 if every valid non-empty delegation has negative sum.

大意

有n个人,每个人擅长m种科目之一,要求选人参加某些科目,且保证每个科目参加的人数相同。(可以选择不参加某些科目,可能有人的贡献是负的(比如本菜))

思路

其实就是把相同科目的人放在一起排个序,然后维护一下前缀和,最后贪心扫一下。这一题比较坑的是范围比较大,1e5*1e5开数组肯定存不下。一开始写了个结构体,结果暴力部分复杂度最坏上到1e10,然后就tle了。翻题解找到大神用vector写的题解,厚颜无耻地抄袭了一下。算是学习了一下vector,因为以前基本没用到。

题解//自己稍作修改

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = int(1e5) + 7;
vector<int> project[maxn];
vector<ll> sum[maxn];
int n, m, id[maxn], max_len;

int main() {

//读入
scanf("%d%d", &n, &m);
for (int i = 1, x, y; i <= n; i++) {
scanf("%d%d", &x, &y);
project[x].push_back(y);//将同科目放进一个vector里
}

//对科目按人数排序
for (int j = 1; j <= m; j++) id[j] = j;
sort(id + 1, id + 1 + m, [](int x, int y) { return project[x].size() > project[y].size(); });//lambda表达式

//生成前缀和
for (int i = 1; i <= m; i++) {
int cur = id[i];
if (project[cur].empty()) break;
int len = int(project[cur].size());

max_len = len>max_len?len:max_len;//求最大人数

sort(project[cur].begin(), project[cur].end(), greater<int>());//greater<class>内部是一个大小比较
sum[cur].resize(project[cur].size());//开一个前缀和的vector
sum[cur][0] = project[cur][0];
for (int j = 1; j < len; j++) sum[cur][j] = sum[cur][j - 1] + project[cur][j];
}

//暴力贪心
ll ans = 0;
for (int i = 1; i <= max_len; i++) {
ll ans_buf = 0;
for (int j = 1; j <= m; j++) {
int cur = id[j];
if (project[cur].size() < i) break;//人不够
if (sum[cur][i - 1] > 0) ans_buf += sum[cur][i - 1];//保证是正的才加
}
ans = ans>ans_buf?ans:ans_buf;
}
printf("%lld\n", ans);
return 0;
}

这里用到一个lambda表达式从c++11开始支持,似乎devc编译会warning。具体语法如下

[capture list] (parameter list){ function body };

其中除了capture list(内部可为空)和function body,其他可选。lambda表达式可以简单理解成一个不需要声明,没有函数名,只需要在使用时简单定义的函数,主要用途是看起来比较厉害而且可以简化函数。比如本题中

sort(id + 1, id + 1 + m, [](int x, int y) { return project[x].size() > project[y].size(); });

可以换成

sort(id + 1, id + 1 + m,cmp);

再在外面定义一个

bool cmp(int x,int y){
return project[x].size()>project[y].size();
}

顺便一提,使用sort对vector排序时,要保证vector开在全局。

感谢Lucien的题解 https://www.lucien.ink/archives/351/

猜你喜欢

转载自www.cnblogs.com/wengsy150943/p/10162503.html