// 20 points
#include <bits/stdc++.h>
using namespace std;
struct Node{
string Address;
int flag;
};
int main() {
int n, k, Data;
string first, Address, Next;
map<int, Node> toNode;
map<string, string> toNext;
map<string, int> toData;
vector<int> minus, insideK, outsideK, ans;
cin >> first >> n >> k;
for(int i = 0;i < n; i++){
cin >> Address >> Data >> Next;
// 存放Address下一个地址Next
toNext[Address] = Next;
toData[Address] = Data;
// 判断分类
if(Data < 0) toNode[Data] = {Address, 1};
else if(0 <= Data && Data <= k)toNode[Data] = {Address, 2};
else toNode[Data] = {Address, 3};
}
while(first != "-1"){
// 获取地址的Data 判断flag分类到不同vector中
if(toNode[toData[first]].flag == 1) minus.push_back(toData[first]);
if(toNode[toData[first]].flag == 2) insideK.push_back(toData[first]);
if(toNode[toData[first]].flag == 3) outsideK.push_back(toData[first]);
first = toNext[first];
}
for(auto m: minus) ans.push_back(m);
for(auto i: insideK) ans.push_back(i);
for(auto o: outsideK) ans.push_back(o);
int i;
for(i = 0; i < ans.size() - 1; i++)
cout << toNode[ans[i]].Address << " " << ans[i] << " " << toNode[ans[i+1]].Address << endl;
cout << toNode[ans[i]].Address << " " << ans[i] << " " << -1 << endl;
}
// AC
#include <bits/stdc++.h>
using namespace std;
struct Node{
int Data, Next;
}List[100001];
int main() {
int n, k, Data, start, Address, Next;
vector<int> v[3];
cin >> start >> n >> k;
for(int i = 0;i < n; i++){
scanf("%d %d %d", &Address, &Data, &Next);
List[Address] = {Data, Next};
}
while(start != -1){
if(List[start].Data < 0) v[0].push_back(start);
if(0 <= List[start].Data && List[start].Data <= k) v[1].push_back(start);
if(k < List[start].Data) v[2].push_back(start);
start = List[start].Next;
}
int i, first = 0;
for(i = 0; i < 3; i++)
for(int j = 0; j < v[i].size(); j++)
if(first++ == 0)
printf("%05d %d ", v[i][j], List[v[i][j]].Data);
else
printf("%05d\n%05d %d ", v[i][j], v[i][j], List[v[i][j]].Data);
printf("-1\n");
}
下面用 Data 索引 Address 和 Next 的方式是不可取的,因为 Data 可能是重复的,可能有多个 1 但对应不同地址,而用同一个值来映射不同的输出,显然是做不到的。所以只能反过来,用多个不同的地址来映射 Data 。
输出的时候参考的代码用了以前没有见过的方式,因为是三行 vector 一起输出,所以不能够像以前一行向量直接读取下一个向量元素。
不过可以看到,一个结点的下一个结点地址就是下一个结点的地址。所以只需要当前结点不输出下一个结点的地址,而下一个结点多输出一次本结点的地址,分别当作上一个结点的下一结点地址与当前结点的地址即可。
if(first++ == 0)
printf("%05d %d ", v[i][j], List[v[i][j]].Data);
else
printf("%05d\n%05d %d ", v[i][j], v[i][j], List[v[i][j]].Data);
输出的时候因为地址的数据是 int 但是需要高位补零所以用了 %05d 这个跟 cout 的 setw() 和 setfill() 作用类似。
(不可取思路)
PAT (Basic Level) 1025 反转链表 (25 point(s))
借鉴了之前这题的解法,只不过当时是根据位置改变位置,此题是根据数据 Data 来排序,所以需要把原本解法的地址对数据索引改为数据向地址索引。
但是写完后超时了,当时考虑就避免了二重循环了,因为数据集规模是 10^5 ,多次循环可能有超时可能。但是没想到常数规模的还是超时了。
虽然上面说这里的思路不可取,但是用 map 来索引和分类的思路是没有什么问题的。只不过用来索引的对象搞错了。
这题取 cin cout 可能会超时,得改成 scanf 和 printf 。PAT用下面这个东西日常没有卵用。
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
sync_with_stdio和cin.tie(0); cout.tie(0);
但是按照错误思路的话,虽然修好了 cin cout 超时的问题,但不能避免由于重复的 Data 导致地址被覆盖,还是卡测试点五。得用地址 Address 来索引前提变量。
以后用 map 或 set 的时候得考虑数据的 key 是否有重复。
当时也有考虑用 unordered_multimap 但该容器重复的 key 是按照填入顺序来排序的,而要实际顺序还是得按照前后地址的索引来遍历,跟填入的顺序没有关系。
当然也可以先用一个散列数组放入数据,再根据顺序放入 unordered_multimap 。但如果都用这么大的散列了,还不如直接用散列数组。