题解: 1、数据太大,一看到题就想该怎么存下这样的树(脑抽到想用数组或链表那种)。想想就可以发现树的每一层数据只是循环移动而没有改变,那么根据二叉树的特性是可以知道树某一层的所有值的。所以我们只需要62层(数组)来记录一下层的数据偏移量就行了。 2、执行操作1,就直接给层的偏移量deep[i]加上偏移值k(通过给k加上2e64然后对层起始值取模来保证偏移量为正值)。 3、执行操作2,要循环对层以及层以下所有层都加上偏移量k,维护正值和2同理,当前层的下一层的k要乘2。 4、特判查询数值1的情况。 5、先输出查询值,然后获得查询值在所在层的下标。对上层的下标计算直接除以2即可,计算每层值和相应的上层下标,值out用层起始值+下标-偏移量再取模得到,输出时要加上层起始值。 6、最重要的就是计算下标、偏移量、根据下标与偏移量计算每层对应的值这几条公式的推导。 7、由于数据量很大,所以pow的计算量很大,这里用数组保存直接使用。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 62;
const long long mod = pow(2,62);
long long deep[maxn];
long long real_mod[maxn];
void init(){
real_mod[0] = 1;
for(int i=1;i<maxn;i++)
real_mod[i] = real_mod[i-1] << 1;
}
int main(){
init();
int q,t;
long long x,k;
scanf("%d",&q);
while(q--){
scanf("%d%lld",&t,&x);
int lo = log2(x);//当前层
if(t<3){
scanf("%lld",&k);
k += mod;
if(t==1){
k %= real_mod[lo];
deep[lo] += k; //深度偏移量
deep[lo] %= real_mod[lo]; //取模
}
else {
k %= real_mod[lo];
int tag = 0;
for(int i=lo;i<maxn;i++){ //深度偏移
deep[i] += k * real_mod[i-lo];
deep[i] %= real_mod[i];
}
}
}
else {
long long out,now = x + deep[lo]; //当前点的下标
now %= real_mod[lo]; //当前点的下标
if(x==1){
printf("%lld\n",x);
continue;
}
printf("%lld",x);
now /= 2;
lo--;
for(;lo>=0;lo--){
out = real_mod[lo]+now-deep[lo]; //out当前输出值
out %= real_mod[lo];
printf(" %lld",out+real_mod[lo]);
now /= 2;
}
printf("\n");
}
}
return 0;
}