[语言月赛202306] 纸条 题解
Source & Knowledge
2023 年 6 月语言月赛,由洛谷网校入门计划/基础计划提供。
题目大意
有
题目分析
本题考察数组的运用。
经过思考可以发现:除了时间最早的纸条,即排好序后的第一张纸条以外,所有的纸条都会出现在某一张纸条的后方,也就都会被提及——如果一张处于一段连贯内容的开头,就会在前一张纸条的输入部分被提及,否则,就会在连贯内容的前面的纸条中被提及。而第一张纸条在一段连贯内容的开头,但前面已经没有纸条了,所以不会被提及。所以,可以建立一个
知道了开头就好办了。我们对每一张纸条开一个数组,从开头的纸条开始,先把它的连贯内容之后的纸条依次输出,然后,通过连贯内容最后一张纸条得到下一段连贯内容的开头,再把之后的输出……以此类推,直到发现了结束标志 -1,输出就停止。
数组的存储方式有两种,一是开一个二维数组,这样空间开销有一点大,但也没有问题。第二种方法是使用 vector 存储,能够动态申请空间,且长度可以直接查询,非常方便。这里给出使用 vector 的核心代码:
vector<int>p[2010];
bool vis[2010];
for(int i=1;i<=n;i++){
cin >> m;
if(m)
for(int j=1;j<=m;j++){
int x;
cin >> x;
vis[x]=1;
p[i].push_back(x);//vector的插入
}
else {
int x=read();
if(x>0)vis[x]=1;//注意防止数组越界
p[i].push_back(x);
}
}
int s;
for(int i=1;i<=n;i++)if(!vis[i])s=i;//寻找起点
while(1){
if(s==-1)return 0;//遇到终点,程序结束
int siz=p[s].size();//这个函数指的是p[s]中的元素个数
cout <<s<<" ";
if(p[s][siz-1]==-1)return 0;//s是终点,程序结束
for(int i=0;i<siz;i++)cout <<p[s][i]<<" ";//依次输出,注意 vector 的下标从0开始
s=p[p[s][siz-1]][0];//vector 的下标从 0 开始,故最后一个元素的下标为 siz-1
}