您的位置:首页 > 其它

Codeforces 792D Paths in a Complete Binary Tree【二进制思维】

2017-03-29 13:09 323 查看
D. Paths in a Complete Binary Tree

time limit per test
3 seconds

memory limit per test
256 megabytes

input
standard input

output
standard output

T is a complete binary tree consisting of
n vertices. It means that exactly one vertex is a root, and each vertex is either a leaf (and doesn't have children) or an inner node (and has exactly two children). All leaves of a complete binary tree have the same depth
(distance from the root). So n is a number such that
n + 1 is a power of
2.

In the picture you can see a complete binary tree with
n = 15.



Vertices are numbered from 1 to
n in a special recursive way: we recursively assign numbers to all vertices from the left subtree (if current vertex is not a leaf), then assign a number to the current vertex, and then recursively assign numbers to all vertices from the right
subtree (if it exists). In the picture vertices are numbered exactly using this algorithm. It is clear that for each size of a complete binary tree exists exactly one way to give numbers to all vertices. This way of numbering is called
symmetric.

You have to write a program that for given n answers
q queries to the tree.

Each query consists of an integer number ui (1 ≤ ui ≤ n) and a string
si, where
ui is the number of vertex, and
si represents the path starting from this vertex. String
si doesn't contain any characters other than 'L', 'R' and 'U',
which mean traverse to the left child, to the right child and to the parent, respectively. Characters from
si have to be processed from left to right, considering that
ui is the vertex where the path starts. If it's impossible to process a character (for example, to go to the left child of a leaf), then you have to skip it. The answer is the number
of vertex where the path represented by si ends.

For example, if ui = 4 and
si = «UURL», then the answer is
10.

Input
The first line contains two integer numbers n and
q (1 ≤ n ≤ 1018,
q ≥ 1). n is such that
n + 1 is a power of
2.

The next 2q lines represent queries; each query consists of two consecutive lines. The first of these two lines contains
ui (1 ≤ ui ≤ n), the second contains non-empty string
si.
si doesn't contain any characters other than 'L', 'R' and 'U'.

It is guaranteed that the sum of lengths of si (for each
i such that 1 ≤ i ≤ q) doesn't exceed
105.

Output
Print q numbers,
i-th number must be the answer to the i-th query.

Example

Input
15 2
4
UURL
8
LRLLLLLLLL


Output
10
5


题目大意:

给你一个具有N个点的完全二叉树,其中有Q个查询,每次查询先给出一个点,作为基础点u,然后对于其有一个字符串操作,每个位子上的操作表示:

L:向u的左儿子走。

R:向u的右儿子走。

U:走到父亲节点。

给出一个字符串,问从u点最终走到了哪个编号的节点上去。

思路:

1、问题肯定是考虑如何改变编号的,我们如果能够动态的改变一个点的编号,那么问题就很容易解决了。

观察到从8走向1,其递减的趋势是4 2 1.明显有二进制趋势。

同理在观察到从8走向15,其递增的趋势也是4 2 1.那么我们不妨在二进制上做一做文章。

2、首先我们将一个具有8个节点的完全二叉树的所有编号都写成二进制形式:



很容易观察到,对应三种操作:

①L:将二进制表示中的最右边的那个1右移一位 (不能移动出界).

②R:将二进制表示中的最右边的那个1的后边哪位上加个1(如果有1就不加了).

③U:将二进制表示中的最右边的那个1前移一位(不能移动出界).

3、注意二进制越界问题。

Ac代码:

#include<stdio.h>
#include<string.h>
#include<math.h>
using namespace std;
#define ll __int64
char a[1005000];
int num[10000];
ll n,m,cnt;
void Getnum(ll u)
{
memset(num,0,sizeof(num));
int tmp=0;
while(u)
{
num[tmp++]=u%2;
u/=2;
}
}
void Getcnt()
{
ll uuu=n/2+1;
while(uuu)
{
uuu/=2;
cnt++;
}
}
ll poww(ll contz)
{
ll ans=1;
while(contz)
{
contz--;
ans*=2;
}
return ans;
}
int main()
{
while(~scanf("%I64d%I64d",&n,&m))
{
cnt=0;
Getcnt();
while(m--)
{
ll u;
scanf("%I64d",&u);
Getnum(u);
scanf("%s",a);
int len=strlen(a);
for(int i=0;i<len;i++)
{
if(a[i]=='L')
{
for(int i=0;i<cnt;i++)
{
if(num[i]==1)
{
if(i!=0)num[i]=0,num[i-1]=1;
break;
}
}
}
if(a[i]=='R')
{
for(int i=0;i<cnt;i++)
{
if(num[i]==1)
{
if(i!=0) num[i-1]=1;
break;
}
}
}
if(a[i]=='U')
{
for(int i=0;i<cnt;i++)
{
if(num[i]==1)
{
if(i!=cnt-1)num[i+1]=1,num[i]=0;
break;
}
}
}
}
ll ans=0;
for(int i=0;i<cnt;i++)
{
if(num[i]==1)
ans+=poww(i);
}
printf("%I64d\n",ans);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Codeforces 792D