记录59
cpp
#include<bits/stdc++.h>
using namespace std;
struct node{
int num;
int w;
}a[20010]={};
bool cmp(node x,node y){
if(x.w==y.w) return x.num<y.num;
else return x.w>y.w;
}
int e[15]={};
int main(){
int n,k;
cin>>n>>k;
for(int i=1;i<=10;i++) cin>>e[i];
for(int i=1;i<=n;i++){
cin>>a[i].w;
a[i].num=i;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++) a[i].w+=e[(i-1)%10+1];
sort(a+1,a+n+1,cmp);
for(int i=1;i<=k;i++) cout<<a[i].num<<" ";
return 0;
}
题目传送门
https://www.luogu.com.cn/problem/P1583
突破点
一共有 n 个人(以 1∼n 编号)向佳佳要照片,而佳佳只能把照片给其中的 k 个人。佳佳按照与他们的关系好坏的程度给每个人赋予了一个初始权值 Wi。然后将初始权值从大到小进行排序,每人就有了一个序号 Di(取值同样是 1∼n)。按照这个序号对 10 取模的值将这些人分为 10 类。也就是说定义每个人的类别序号 Ci 的值为 (Di−1)mod10+1,显然类别序号的取值为 1∼10。第 i 类的人将会额外得到 Ei 的权值。你需要做的就是求出加上额外权值以后,最终的权值最大的 k 个人,并输出他们的编号。在排序中,如果两人的 Ei 相同,编号小的优先。
思路
- 存储每个人的权值跟编号 👉 结构体数组
- 权值按照题目要求重新赋值
- 进行排序,先比较权值,相同再比较编号
代码简析
cpp
#include<bits/stdc++.h>
using namespace std;
struct node{
int num;
int w;
}a[20010]={};
bool cmp(node x,node y){
if(x.w==y.w) return x.num<y.num;
else return x.w>y.w;
}
int e[15]={};
int main(){
int n,k;
cin>>n>>k;
....
}
struct node{int num;(编号)int w;(权重)}a[20010]={}; (存储每个人的情况)
bool cmp(node x,node y){} 👉 结构体的比较函数
if(x.w==y.w) return x.num<y.num; 👉权重相同的时候才会比较编号,编号由小到大排序
else return x.w>y.w; 👉 按照权重排序,权重由大到小排序
int e[15]={}; 👉 额外得到 Ei 的权值
int n,(总人数)k;(得到照片的人)
cpp
#include<bits/stdc++.h>
using namespace std;
struct node{
int num;
int w;
}a[20010]={};
bool cmp(node x,node y){
if(x.w==y.w) return x.num<y.num;
else return x.w>y.w;
}
int e[15]={};
int main(){
int n,k;
cin>>n>>k;
for(int i=1;i<=10;i++) cin>>e[i];
for(int i=1;i<=n;i++){
cin>>a[i].w;
a[i].num=i;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++) a[i].w+=e[(i-1)%10+1];
sort(a+1,a+n+1,cmp);
for(int i=1;i<=k;i++) cout<<a[i].num<<" ";
return 0;
}
先按照权重排序,然后得到新的权重
for(int i=1;i<=n;i++) a[i].w+=e[(i-1)%10+1]; 👉 每个人的类别序号 Ci 的值为 (Di−1)mod10+1
接着按照最终的权重再次排序
sort(a+1,a+n+1,cmp); 👉 最终人数排列的情况
for(int i=1;i<=k;i++) cout<<a[i].num<<" "; 👉 k个得到照片的人
补充
在CSP-J竞赛中,对结构体进行多标准排序是高频操作。以下是两种核心方法 和竞赛金牌模板:
方法一:重载
<运算符(最推荐)直接在结构体内部重载
<,sort()会自动使用此规则。模板:按分数降序,分数相同按ID升序
cppstruct Student { int id; int score; // 按分数降序(主标准),分数相同按ID升序(次标准) bool operator < (const Student& other) const { if (score != other.score) { return score > other.score; // 主标准:降序(用>) } return id < other.id; // 次标准:升序(用<) } }; // 使用 vector<Student> v; sort(v.begin(), v.end()); // 自动调用operator<多标准扩展(三标准)
cppstruct Node { int a, b, c; // 按a降序,a相同按b升序,b相同按c降序 bool operator < (const Node& other) const { if (a != other.a) return a > other.a; // a降序 if (b != other.b) return b < other.b; // b升序 return c > other.c; // c降序 } };必须记住的规矩:
**
const不能漏** :必须是const` 成员函数返回
bool:返回true表示"当前对象应排在前面"主标准放前面 :用
if判断主标准,次标准放后面
方法二:Lambda表达式(最灵活)
不修改结构体,外部定义排序规则。
模板(与上面等价)
cppstruct Student { int id, score; }; sort(v.begin(), v.end(), [](const Student& a, const Student& b) { if (a.score != b.score) { return a.score > b.score; // 主标准:分数降序 } return a.id < b.id; // 次标准:ID升序 });Lambda优势:多规则复用
cpp// 规则1:按分数降序 auto cmp1 = [](const Student& a, const Student& b) { return a.score > b.score; }; // 规则2:按ID升序 auto cmp2 = [](const Student& a, const Student& b) { return a.id < b.id; }; sort(v.begin(), v.end(), cmp1); // 按分数排 sort(v.begin(), v.end(), cmp2); // 再按ID排
三、竞赛金牌模板(背下来)
cpp#include <bits/stdc++.h> using namespace std; struct Node { int a, b, c; // 万能三标准排序(降序→升序→降序) bool operator < (const Node& other) const { if (a != other.a) return a > other.a; // a降序 if (b != other.b) return b < other.b; // b升序 return c > other.c; // c降序 } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); vector<Node> v; int n; cin >> n; for (int i = 0; i < n; i++) { cin >> v[i].a >> v[i].b >> v[i].c; } // 一次排序搞定 sort(v.begin(), v.end()); // 输出 for (auto &x : v) { cout << x.a << " " << x.b << " " << x.c << "\n"; } return 0; }
四、常见错误与调试
错误代码 结果 正确写法 bool operator < (Student other)❌ 编译错误 bool operator < (const Student& other) constreturn a.score > b.score;❌ 漏次标准 if (a.score != b.score) return a.score > b.score;return score > other.score && id > other.id;❌ 逻辑错误 用 if分主次,不能&&sort(v.begin(), v.end(), cmp);❌ cmp未定义 auto cmp = [](...){...};
五、一句话总结
CSP-J结构体多标准排序 = 重载
<运算符 + 主标准if判断 + 次标准else返回 + 必须加const,Lambda更灵活但代码稍长。