gesp(C++六级)(13)洛谷:P11375:[GESP202412 六级] 树上游走
gesp(C++六级)(13)洛谷:P11375:[GESP202412 六级] 树上游走
题目描述
小杨有一棵包含无穷节点的二叉树(即每个节点都有左儿子节点和右儿子节点;除根节点外,每个节点都有父节点),其中根节点的编号为 1 1 1,对于节点 i i i,其左儿子的编号为 2 × i 2\times i 2×i,右儿子的编号为 2 × i + 1 2\times i + 1 2×i+1。
小杨会从节点 s s s 开始在二叉树上移动,每次移动为以下三种移动方式的任意一种:
- 第 1 种移动方式:如果当前节点存在父亲节点,向上移动到当前节点的父节点,否则不移动;
- 第 2 种移动方式:移动到当前节点的左儿子;
- 第 3 种移动方式:移动到当前节点的右儿子。
小杨想知道移动 n n n 次后自己所处的节点编号。数据保证最后所处的节点编号不超过 1 0 12 10^{12} 1012。
输入格式
第一行包含两个正整数 n n n 和 s s s,代表移动次数和初始节点编号。
第二行包含一个长度为 n n n 且仅包含大写字母 U \tt{U} U、 L \tt{L} L 和 R \tt{R} R 的字符串,代表每次移动的方式,其中 U \tt{U} U 代表第 1 种移动方式, L \tt{L} L 代表第 2 种移动方式, R \tt{R} R 代表第 3 种移动方式。
输出格式
输出一个正整数,代表最后所处的节点编号。
样例 #1
样例输入 #1
3 2
URR
样例输出 #1
7
提示
小杨的移动路线为 2 → 1 → 3 → 7 2 \to 1 \to 3 \to 7 2→1→3→7。
子任务编号 | 数据点占比 | n n n | s s s |
---|---|---|---|
1 1 1 | 20 % 20\% 20% | ≤ 10 \leq 10 ≤10 | ≤ 2 \leq 2 ≤2 |
2 2 2 | 20 % 20\% 20% | ≤ 50 \leq 50 ≤50 | ≤ 10 \leq 10 ≤10 |
3 3 3 | 60 % 60\% 60% | ≤ 1 0 6 \leq 10^6 ≤106 | ≤ 1 0 12 \leq 10^{12} ≤1012 |
对于全部数据,保证有 1 ≤ n ≤ 1 0 6 1\leq n\leq 10^6 1≤n≤106, 1 ≤ s ≤ 1 0 12 1\leq s\leq 10^{12} 1≤s≤1012。
AC代码(100分)
#include<bits/stdc++.h>
using namespace std;
/*思路:
按题意模拟,需要特别注意这个点:
题目只说最后所处的节点编号不超过10^12,
没有说经过的节点编号不超过10^12,如果超过会爆long long
解决方案:一旦编号超过10^12,就暂时不进行2和3移动,记下来等到进行1移动时抵消掉
*/
const int INF=1e12;
long long n,s,cnt;//cnt用于统计中间过程中超过10^12的次数
char c;
int main(){
cin>>n>>s;
for(long long i=1;i<=n;i++){
cin>>c;
if(c=='U'){//移动到父节点
if(cnt!=0){
cnt--;//抵消
continue;//停止本次循环,继续下次循环
}
if(s!=1) s=s/2;
}else if(c=='L'){//移动到左儿子
if(s*2>INF) cnt++;
else s=s*2;
}else{//移动到右儿子
if(s*2>INF) cnt++;
else s=s*2+1;
}
}
cout<<s;
return 0;
}
文末彩蛋:
点击王老师青少年编程主页有更多精彩内容