题目链接:http://codeforces.com/problemset/problem/792/D
题意:
给出一个包含n个结点的完全二叉树,并且结点的编号是按中序遍历的顺序标号的,接下来有q个询问,每个询问包括一个点m表示你现在在编号为m的电上,和一个长度为u的字符串,字符串包括(U、L、R)表示向上、向左、向右,如果不能移动的话保持在原位。
题解:
观察中序遍历编号的二叉树我们可以得到一个点的左子树编号和右子树编号与改点的深度和最大深度有关,得到相应的关系即可模拟在二叉树上走。
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<stdlib.h>
#include <string.h>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<time.h>
#include<sstream>
using namespace std;
#define MAX_N 55
#define inf 0x7f7f7f7f
#define LL long long
#define ull unsigned long long
const LL INF = 1e18;
const double Pi = acos(-1);
const int mod = 1e4+7;
typedef pair<int, int>P;
LL pow2(int x)
{
LL ans = 1;
while(x) {
x--;
ans *= 2;
}
return ans;
}
int main()
{
LL n, q;
cin >> n >> q;
//向下寻路时保存向左还是向右
while(q--) {
LL m;
char s[100005];
cin >> m;
scanf("%s", &s);
LL d, maxd;
maxd = log2(n);
LL p = (n+1)/2;
d = 0;
int path[100005];
int l = 0;
while(p != m) {
LL pp = pow2(maxd-d-1);
LL lc = p-pp;
LL rc = p+pp;
LL maxc = lc + pp - 1;//左子树下的最大值
if(maxc >= m)
p = lc, d++, path[++l] = 0;
else
p = rc, d++, path[++l] = 1;
}
int len = strlen(s);
for(int i=0; i<len; i++) {
if(s[i] == 'U') {
if(!l)
continue;
LL pp = pow2(maxd-d);
if(path[l] == 0)
p += pp;
else
p -= pp;
d--;
l--;
}
else if(s[i] == 'L') {
if(d == maxd)
continue;
LL pp = pow2(maxd-d-1);
d++;
path[++l] = 0;
p -= pp;
}
else {
if(d == maxd)
continue;
LL pp = pow2(maxd-d-1);
d++;
path[++l] = 1;
p += pp;
}
}
cout << p << endl;
}
}