[CF960D] Full Binary Tree Queries

Description

给定一棵无限层的满二叉树,如果 (x) 是根,那么左孩子是 (2x),右孩子是 (2x+1)。现在有三种操作:将 (x) 所在层的所有节点整体向右循环移动 (k) 个单位;将 (x) 所在层的所有节点及其子树整体向右循环移动 (k) 个单位;输出 (x) 到根的路径。

Solution

实际上,由于访问到的层数不会超过 (63),我们只需要暴力记录每一层被循环移动的次数即可。对于第一种操作修改当层即可;对于第二种操作修改其后的所有层即可。

对于询问,我们只需要反解出实际位置,就得到了路径上所有点的位置,再把位置换算回下标即可。本质上,我们只需要提供位置和下标之间的换算即可。

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 63;

int offset[N],n,t1,t2,t3,t4;

int get_level(int p)
{
    return log2(p);
}

int pos2id(int p)
{
    int level=get_level(p);
    p=(p+(1ll<<level)+offset[level])%(1ll<<level)+(1ll<<level);
    return p;
}

int id2pos(int p)
{
    int level=get_level(p);
    p=(p+(1ll<<level)-offset[level])%(1ll<<level)+(1ll<<level);
    return p;
}

signed main()
{
    ios::sync_with_stdio(false);

    cin>>n;
    while(n--)
    {
        cin>>t1;
        if(t1==1)
        {
            cin>>t2>>t3;t3=-t3;
            int level=get_level(t2);
            offset[level]+=t3;
            offset[level]%=1ll<<level;
            offset[level]+=1ll<<level;
            offset[level]%=1ll<<level;
        }
        if(t1==2)
        {
            cin>>t2>>t3;t3=-t3;
            int level=get_level(t2);
            t3%=1ll<<level;
            t3+=1ll<<level;
            t3%=1ll<<level;
            for(int i=level;i<N;i++)
            {
                offset[i]+=t3;
                offset[i]%=1ll<<i;
                offset[i]+=1ll<<i;
                offset[i]%=1ll<<i;
                t3*=2;
            }
        }
        if(t1==3)
        {
            cin>>t2;
            t2=id2pos(t2);
            /*cout<<"offset: ";
            for(int i=0;i<4;i++) cout<<offset[i]<<" ";
            cout<<endl;*/
            while(t2!=0)
            {
                cout<<pos2id(t2)<<" ";
                t2>>=1;
            }
            cout<<endl;
        }
    }
}

原文地址:https://www.cnblogs.com/mollnn/p/13599869.html