二叉树的每一层进行旋转。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 65;
ll Move1[maxn];///正移动偏移量,方便知道原节点去了哪个位置
void op1(int lay,ll move,ll x,ll times)
{
if(x) lay=log2(x)+1; //多少层
ll base=1ll<<(lay-1);//这一层有多少元素
if(times==-1) move%=base;
else move=((move%base)*(times%base))%base;
//计算偏移量
Move1[lay]=((Move1[lay]+move)%base+base)%base;
}
void op2(ll move,ll x){
int lay=log2(x)+1;
for(int i=lay,j=0;i<65;i++,j++){
op1(i,move,0,1ll<<j);
}
}
void op3(ll x){
if(x==1ll){
puts("1");
return ;
}
printf("%lld",x);
int lay=log2(x)+1;
ll base=1ll<<(lay-1);
//计算当前节点的位置
ll pos=((x-base+Move1[lay])+base)%base+base;
while(pos!=2ll&&pos!=3ll){
pos/=2;
lay=log2(pos)+1;
base=1ll<<(lay-1);
printf(" %lld",((pos-Move1[lay]-base)+base)%base+base);
}puts(" 1");
}
int main(void)
{
int n;
scanf("%d",&n);
while(n--){
int cmd;
scanf("%d",&cmd);
ll x,k;
if(cmd==1){
scanf("%lld%lld",&x,&k); ///x是节点值,k是移动次数。
op1(-1,k,x,-1);
}else if(cmd==2){
scanf("%lld%lld",&x,&k);
op2(k,x);
}else{
scanf("%lld",&x);
op3(x);
}
}
return 0;
}