小苯送礼物
思路
这道题说白了就是一个自定义排序问题。小苯要从 n 个粉丝里选 k 个送礼物,怎么选?按"支持力度"来排。
支持力度怎么算?点赞算 1 点,收藏算 2 点,所以一个粉丝的支持力度 = 赞数 + 2 * 收藏数。
那如果两个粉丝支持力度一样呢?题目给了两层 tiebreak:
- 先比收藏数,收藏多的优先
- 收藏也一样?编号小的优先
选出前 k 名后,按编号升序输出就行。
具体做法
- 读入每个粉丝的赞数和收藏数,算出支持力度,记下编号
- 按照"支持力度降序 → 收藏数降序 → 编号升序"的规则排序
- 取前 k 个粉丝的编号,排个序输出
就是个排序题,关键在写对比较函数。没什么算法上的难度,考的是细心。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, k;
scanf("%d%d", &n, &k);
vector<array<int, 3>> fans(n); // {支持力度, 收藏数, 编号}
for (int i = 0; i < n; i++) {
int likes, col;
scanf("%d%d", &likes, &col);
fans[i] = {likes + 2 * col, col, i + 1};
}
// 支持力度降序 → 收藏数降序 → 编号升序
sort(fans.begin(), fans.end(), [](const auto& a, const auto& b) {
if (a[0] != b[0]) return a[0] > b[0];
if (a[1] != b[1]) return a[1] > b[1];
return a[2] < b[2];
});
vector<int> res;
for (int i = 0; i < k; i++) {
res.push_back(fans[i][2]);
}
sort(res.begin(), res.end()); // 按编号升序输出
for (int i = 0; i < k; i++) {
if (i) printf(" ");
printf("%d", res[i]);
}
printf("\n");
return 0;
}
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int k = Integer.parseInt(st.nextToken());
int[][] fans = new int[n][3]; // 支持力度, 收藏数, 编号
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
int likes = Integer.parseInt(st.nextToken());
int col = Integer.parseInt(st.nextToken());
fans[i][0] = likes + 2 * col;
fans[i][1] = col;
fans[i][2] = i + 1;
}
// 支持力度降序 → 收藏数降序 → 编号升序
Arrays.sort(fans, (a, b) -> {
if (a[0] != b[0]) return b[0] - a[0];
if (a[1] != b[1]) return b[1] - a[1];
return a[2] - b[2];
});
int[] res = new int[k];
for (int i = 0; i < k; i++) {
res[i] = fans[i][2];
}
Arrays.sort(res); // 按编号升序输出
StringBuilder sb = new StringBuilder();
for (int i = 0; i < k; i++) {
if (i > 0) sb.append(' ');
sb.append(res[i]);
}
System.out.println(sb);
}
}
import sys
input = sys.stdin.readline
n, k = map(int, input().split())
fans = []
for i in range(n):
likes, col = map(int, input().split())
support = likes + 2 * col
fans.append((support, col, i + 1))
# 支持力度降序 → 收藏数降序 → 编号升序
fans.sort(key=lambda x: (-x[0], -x[1], x[2]))
res = sorted(fans[i][2] for i in range(k))
print(' '.join(map(str, res)))
const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin });
const lines = [];
rl.on('line', line => lines.push(line));
rl.on('close', () => {
const [n, k] = lines[0].split(' ').map(Number);
const fans = [];
for (let i = 0; i < n; i++) {
const [likes, col] = lines[i + 1].split(' ').map(Number);
fans.push([likes + 2 * col, col, i + 1]);
}
// 支持力度降序 → 收藏数降序 → 编号升序
fans.sort((a, b) => {
if (a[0] !== b[0]) return b[0] - a[0];
if (a[1] !== b[1]) return b[1] - a[1];
return a[2] - b[2];
});
const res = [];
for (let i = 0; i < k; i++) {
res.push(fans[i][2]);
}
res.sort((a, b) => a - b);
console.log(res.join(' '));
});
复杂度
- 时间复杂度:
,排序的开销
- 空间复杂度:
,存储粉丝信息
总结
这道题没什么弯弯绕,就是考你会不会写自定义排序的比较函数。三个排序关键字:支持力度、收藏数、编号,前两个降序第三个升序,写对了就能过。唯一要注意的是支持力度的计算公式:赞数 1 + 收藏数 2,别搞反了权重。最后输出别忘了按编号升序排一下。



京公网安备 11010502036488号