L2-3 浪漫侧影 - 2024天梯赛JXNU模拟4 (pintia.cn)
题意:其实就是让根据中序序列和后序序列建树,然后输出左视图和右视图,左视图就是在层序遍历序列中每一层中最左边的点,右视图就是在层序遍历序列中每一层中最右边的点。
思路:建树方式 + 便建树边层序(看代码即可)
这里有两个比较好的思想,一个是建树方式,一个是在建树的过程中对层序遍历序列进行存储
根据中序序列和后序序列建树的思想:中序左根右,后序左右根,所以后序序列的最后一个字母即是根节点,然后在中序序列中找到该根节点的位置,将序列分成左右两部分(即左右两子树),于是即可把后序序列也分成左右两部分,然后递归的去对左右子树做同种操作就可以了,直到中序序列长度为0时,说明树已经分完了(树建好了)
层序序列就是每一次递归操作中,在后序序列中找出的根节点
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 30;
vector<int> ans[N]; //存每一层的层序遍历序列
int maxd;
void dfs(string in, string post, int deep)
{
if(!in.size()) return;
char k = post[post.size() - 1]; //找到是每一层子树的根
int pos = in.find(k); //找到当前根在中序序列中的位置
ans[deep].push_back(k - '0'); //边建树边层序
maxd = max(maxd, deep); //更新深度
dfs(in.substr(0, pos), post.substr(0, pos), deep + 1); //递归的去做左右子树
dfs(in.substr(pos + 1), post.substr(pos, post.size() - 1 - pos), deep + 1);
}
signed main()
{
int n;
cin >> n;
string in;
string post;
for(int i = 1; i <= n; i ++ ) //转换成字符序列方便操作
{
int x;
cin >> x;
in += (x + '0');
}
for(int i = 1; i <= n; i ++ )
{
int x;
cin >> x;
post += (x + '0');
}
dfs(in, post, 1);
cout << maxd << " ";
cout << "R: " << endl;
for(int i = 1; i <= maxd; i ++ )
cout << ans[i][ans[i].size() - 1] << " ";
cout << endl;
cout << "L: " << endl;
for(int i = 1; i <= maxd; i ++ )
cout << ans[i][0] << " ";
return 0;
}
L2-043 龙龙送外卖 - 团体程序设计天梯赛-练习集 (pintia.cn)
题意:一个外卖员,动态的给出要送外卖的地点,然后算出每增加一个工作点后的最短路程是多少,注意这里有个阅读理解:每次送完外卖后都要回到外卖站去拿下一份外卖,当所有外卖送完后(即最后一次送外卖送完就可以了)不需要回快递站。
思路:其实读懂题了就相当显然,答案就是sum * 2 - maxd,sum为当前要走的总路程,maxd为当前要走的最大路程(最后一段再走它就好了)
因为要搜索很多次,考虑加入记忆化搜索优化,因为本题给出的是每个子节点的父节点是谁,可以考虑反向搜索,即从子节点往父节点搜索,反向搜索从子节点到根节点的距离
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 1e5 + 10;
int p[N]; //p[i]存的是第i个节点的父节点
int d[N]; //储存第i个节点的最大深度
int sum;
int dfs(int u) //记忆化搜索
{
if(p[u] == -1 || d[u] != 0) return d[u];
sum ++; //神之一手,总路程直接用sum累加即可
d[u] = dfs(p[u]) + 1;
return d[u];
}
void solve()
{
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i ++ ) cin >> p[i];
int maxd = 0;
while(m -- )
{
int x;
cin >> x;
maxd = max(maxd, dfs(x)); //更新加入当前点后的最大距离
cout << sum * 2 - maxd << endl;
}
}
signed main()
{
int t = 1;
while(t -- ) solve();
return 0;
}