这道题算法笔记上面用 sort 来做,不算特别难, 但其实还可以更简单。最近在使用 min_element() 和 max_element() 函数的时候, 发现 sort 排序其实有更简单的另类写法, 并不需要定义 cmp 函数。
这道题我的第一次代码如下(按照算法笔记的思路来的):
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=100010;
struct Node {
int address, data, next;
int order;
Node(){
order=maxn;
}
}node[maxn];
bool cmp(Node a, Node b){
return a.order<b.order;
}
int main(){
int begin, n ,K ,address;
scanf("%d %d %d",&begin, &n, &K);
for (int i=0; i<n; i++){
scanf("%d",&address);
scanf("%d %d",&node[address].data, &node[address].next);
node[address].address=address;
}
int p=begin, count=0;
while (p!=-1){
node[p].order=count++;
p=node[p].next;
}
sort(node, node+maxn,cmp);
n=count;
for (int i=0; i<n/K; i++){
for (int j=(i+1)*K-1; j>i*K; j--){
printf("%05d %d %05d\n",node[j].address, node[j].data, node[j-1].address);
}
printf("%05d %d ",node[i*K].address, node[i*K].data);
if (i<n/K-1){
printf("%05d\n",node[(i+2)*K-1].address);
}else {
if (n%K==0){
printf("-1\n");
}else {
printf("%05d\n",node[(i+1)*K].address);
for (int i=n/K *K; i<n; i++){
printf("%05d %d ",node[i].address, node[i].data);
if (i<n-1){
printf("%05d\n",node[i+1].address);
}else{
printf("-1\n");
}
}
}
}
}
}
非常常规 ,但是容易出错。
第二次做的代码如下(对每个元素先分组, 在赋予组内编号):
//注意几个点 比如说cnt==0 cnt==1这种极端情况 幸好本题并给有考这种极端情况
//第一次尝试在直接在结构体里面对 < 重载 , 不用写cmp 函数了, 但是g++编译器里面通过不了, clang++才行。
#include <cstdio>
#include <algorithm>
using namespace std;
const int INF=1000000000;
struct Node{
int address;
int data;
int next;
int isValid=0;
int group=INF;
int index;
friend bool operator < (const Node &a, const Node &b){
if (a.isValid!=b.isValid) return a.isValid>b.isValid;
else if (a.group!=b.group) return a.group<b.group;
else if (a.index!=b.index) return a.index>b.index;
}
}node[100010];
int main(){
int begin, n, k;
scanf("%d %d %d", &begin, &n, &k);
for (int i=0; i<n; i++){
int address, data, next;
scanf("%d %d %d",&address, &data, &next);
node[address].address=address;
node[address].data=data;
node[address].next=next;
}
int p=begin;
int cnt=0;
while (p!=-1){
node[p].isValid=1;
node[p].group=cnt/k;
node[p].index=cnt%k;
cnt++;
p=node[p].next;
}
sort(node, node+100010);
n=cnt;
if (n%k==0){
for (int i=0; i<cnt-1; i++){
printf("%05d %d %05d\n", node[i].address, node[i].data, node[i+1].address);
}
printf("%05d %d -1\n", node[cnt-1].address, node[cnt-1].data);
}else {
int lastCnt=n/k*k;//值得借鉴
for (int i=0; i<lastCnt-1; i++){
printf("%05d %d %05d\n", node[i].address, node[i].data, node[i+1].address);
}
printf("%05d %d %05d\n", node[lastCnt-1].address, node[lastCnt-1].data, node[cnt-1].address);
for (int i=cnt-1; i>=lastCnt+1; i--){
printf("%05d %d %05d\n", node[i].address, node[i].data, node[i-1].address);
}
printf("%05d %d -1\n", node[lastCnt].address, node[lastCnt].data);
}
}
和第一次有啥区别呢, 主要在sort函数这一块, 我们通常是先定义一个结构体 ,然后再用cmp函数来定义如何排序, 最后用sort(a, a+n, cmp)这种形式来对结构体数组排序。
但其实可以更简单, 直接在定义结构体的时候, 在结构体内部重载 < ,定义大小规则, 这样做有很多好处:
第一, 如果遇到 set, priority_queue这些容器, 可以直接排序。
第二, 可以直接使用 min_element() 和 max_element()来找到结构体数组中想要的最值。
但是, 这种写法 评测的时候 g++ 不支持, 不过 clang++ 支持, btw, g++没有 clang++ 好用, 很多代码如果g++不行, 就换成 clang++ 试试,就能通过。(PATA 1065就是个典型例子)