题目链接:http://codeforces.com/problemset/problem/792/D
题意:给你一颗n个点的完全二叉树,以中序遍历从1-n给每个节点赋值
再给你q和q个询问,每个询问给你x(1<=x<=n)和一堆字符串(表示操作),问你从值为x的节点进行操作后最终得到的值是多少。
操作有三种,U,L,R;
U:到它的父节点,如果是根节点则不变;
L:到他的左儿子节点,如果是叶节点则不变;
R:到他的左儿子节点,如果是叶节点则不变;
分析:
看图找一下规律。发现从下到上第i层的从左到右数第j个节点,值为2^(i-1)+(2^i)*(j-1);(i,j从1开始)
然后发现
每个点到它的父节点 如果是左子树,就加2^(i-1);如果是右子树,就减2^(i-1)。
每个点到他的儿子节点 如果到左儿子,就减2^(i-2);如果到右儿子,就加2^(i-2);
最后再判断一下得到的值是不是1~n的。
然后直接模拟水过。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
char a[100005];
ll n,q;
ll work(char c,ll x)
{
ll b=1,d=0;
for(int i=0;i<=64;i++)
{
if(x%b!=0)
{
d=i;
break;
}
b*=2;
}
ll num=x/b;
if(c=='U')
{
if(num%2==0)
{
d=x+b/2;
}
else
d=x-b/2;
}
else if(c=='R')
{
d=x+b/4;
}
else
{
d=x-b/4;
}
if(d>0&&d<=n)
x=d;
return x;
}
int main()
{
cin>>n>>q;
while(q--)
{
ll x;
scanf("%lld",&x);
scanf("%s",a);
for(int i=0;a[i];i++)
{
x=work(a[i],x);
}
printf("%lld\n",x);
}
}