Codeforces Round #474-D-Full Binary Tree Queries(瞎搞)

D. Full Binary Tree Queries
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

You have a full binary tree having infinite levels.

Each node has an initial value. If a node has value x, then its left child has value x and its right child has value x + 1.

The value of the root is 1.

You need to answer Q queries.

There are 3 types of queries:

  1. Cyclically shift the values of all nodes on the same level as node with value X by K units. (The values/nodes of any other level are not affected).
  2. Cyclically shift the nodes on the same level as node with value X by K units. (The subtrees of these nodes will move along with them).
  3. Print the value of every node encountered on the simple path from the node with value X to the root.

Positive K implies right cyclic shift and negative K implies left cyclic shift.

It is guaranteed that atleast one type 3 query is present.

Input

The first line contains a single integer Q (1 ≤ Q ≤ 105).

Then Q queries follow, one per line:

  • Queries of type 1 and 2 have the following format: T X K (1 ≤ T ≤ 21 ≤ X ≤ 10180 ≤ |K| ≤ 1018), where T is type of the query.
  • Queries of type 3 have the following format: 3 X (1 ≤ X ≤ 1018).
Output

For each query of type 3, print the values of all nodes encountered in descending order.

Examples
input
Copy
5
3 12
1 2 1
3 12
2 4 -1
3 8
output
Copy
12 6 3 1 
12 6 2 1 
8 4 2 1 
input
Copy
5
3 14
1 5 -3
3 14
1 3 1
3 14
output
Copy
14 7 3 1 
14 6 3 1 
14 6 2 1 

题意:给你一个满二叉树,初始每个点的权值为该点的编号,然后有三种操作:

(1)移动权值为x这一层的所有权值k个单位(正便是右移,负表示左移),不影响其它层

(2)移动结点为x这一层的所有节点k个单位,注意该节点的所有子树也要移动。

(3)查询当前权值为x到根节点这一条路径的所有权值。

题解:开一个移位数组标记每层移了多少个单位即可,瞎搞搞就行了。(感觉自己写麻烦了)

#include<stdio.h>
#include<algorithm>
using namespace std;
#define ll long long
int q,t;
ll a[100],b[100];
ll x,k,f[100],mark;
void init()
{
	f[0]=1ll;
	for(ll i=1;i<63;i++)
		f[i]=f[i-1]*2ll;
}
void update1(ll x,ll y)
{
	int p=0;
	while(f[p]<=x && p<63) p++;p--;
	a[p]+=y;
}
void update2(ll x,ll y)
{
	int p=0;
	while(f[p]<=x && p<63) p++;p--;
	ll num=1ll;
	while(p<63) a[p]+=y*num,p++,num*=2ll;
}
void findans(ll x)
{
	if(x==1)
	{
		printf("1\n");
		return;
	}
	int p=0;
	while(f[p]<=x && p<63) p++;p--;
	ll t;
	if(!mark) t=x-f[p]+1+a[p];
	else t=x-f[p]+1-a[p];
	//printf("%lld ",t);
	ll tmp=t/f[p];t-=f[p]*tmp;
	if(t<=0) t+=f[p];
	if(t>f[p]) t-=f[p];
	//printf("%lld %llde\n",x,t);
	if(!mark) printf("%lld ",x);
	else printf("%lld ",t+f[p]-1);
	if(!mark) mark=1,findans((t+f[p]-1)/2);  
	else findans(x/2);
} 
int main(void)
{
	init();     
	scanf("%d",&q);
	while(q--)
	{
		scanf("%d%lld",&t,&x);
		if(t!=3)
		{
			scanf("%lld",&k);        
			if(t==1) update1(x,k);
			else update2(x,k);
		}
		else
			mark=0,findans(x);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值