Codeforces Round #474 D Full Binary Tree Queries 满二叉树操作

题解:
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;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值