• Codeforces 960D Full Binary Tree Queries ( 思维 && 模拟 )


    题意 : 给出一颗无限层的满二叉树,然后每个值为 X (根的 X 等于 1 ) 左孩子的值是 2*X,右孩子的值是 2*X+1 ,现在有两种操作,(1, x,k) 表示将 x 所在层的所有节点整体向右循环地移动 k 个单位、(2,x,k)表示将 x 所在的层的所有节点及其子树向右循环地移动 k 个单位、(3,x)输出从 x 到根的路径

    分析 : 

    第一个操作不难进行模拟

    只要给每个层记录其偏移量,最后查询的时候依据偏移量来输出具体的值即可

    关键是第二个操作

    仔细一想,会发现一个规律

    如果第一层移动 k 个单位

    那么对于第二种操作,其孩子分别移动了 k*2^1、k*2^2、k*2^3……

    所以其本质就是进行第一种操作,偏移量不一样了而已

    查看了题目数据量之后发现每一次只进行到第 60 层

    所以模拟到第 60 层就是回答所有问询了

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int maxn = 65;
    LL Move1[maxn];///正移动偏移量,方便知道原节点去了哪个位置
    LL Move2[maxn];///反移动偏移量,方便知道原节点现在是什么值
    
    inline void op1(int Lay, LL move, LL x, LL times)
    {
        if(x != 0) Lay = log2(x) + 1;///获取 x 在第几层
        LL Base = 1LL<<(Lay-1);///这一层有多少个节点
    
        if(times == -1) move %= Base;///如果非第二种操作
        else move = ( (move % Base) * (times % Base) ) % Base;///第二种操作
    
        Move1[Lay] = (( Move1[Lay] + move) + Base ) % Base;///正偏移量直接移动即可
        Move2[Lay] = (( Move2[Lay] - move) + Base ) % Base;///反偏移量要反向移动
    }
    
    inline void op2(LL move, LL x)
    {
        int Lay = log2(x) + 1;
        for(int i=Lay,j=0; i<65; i++,j++)///最多到60层
            op1(i, move, 0, 1LL<<j);
    }
    
    inline void op3(LL x)
    {
        if(x == 1LL){
            puts("1");
            return;
        }
        printf("%I64d", x);
        int Lay = log2(x) + 1;
        LL Base = 1LL<<(Lay-1);
        LL pos = (( (x - Base) + Move1[Lay] ) + Base) % Base + Base;
        while(!(pos == 3LL || pos == 2LL)){
            
            if(pos & 1) pos = (pos - 1)>>1;///找到当前节点的父亲节点
            else pos = pos>>1;
        
            Lay = log2(pos) + 1;
            Base = 1LL<<(Lay-1);
            
            printf(" %I64d", ( (pos - Base + Move2[Lay]) + Base ) % Base + Base);///通过反向偏移量来获取在这个节点位置的值
        }puts(" 1");
    }
    
    int main(void)
    {
        int Q;
        scanf("%d", &Q);
        while(Q--){
            int command;
            LL X, K;
            scanf("%d", &command);
            if(command == 1){
                scanf("%I64d %I64d", &X, &K);
                op1(-1, K, X, -1);
            }else if(command == 2){
                scanf("%I64d %I64d", &X, &K);
                op2(K, X);
            }else{
                scanf("%I64d", &X);
                op3(X);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    结对作业
    小学算术题四则运算(升级)
    自动生成小学四则运算题目(Python实现)
    《基于CMMI的软件工程及实训指导》第一章 软件工程基础
    使用 python 进行微信好友分析
    中国大学排名
    python小程序测试
    爬虫测试
    体育竞技分析

  • 原文地址:https://www.cnblogs.com/qwertiLH/p/8870226.html
Copyright © 2020-2023  润新知