zoukankan      html  css  js  c++  java
  • [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;
            }
        }
    }
    
    
  • 相关阅读:
    二分多重匹配(HDU5093)
    2-sat(and,or,xor)poj3678
    某个点到其他点的曼哈顿距离之和最小(HDU4311)
    第k最短路A*启发式搜索
    求树的直径和中心(ZOJ3820)
    并查集hdu4424
    map容器结构体离散化
    二维坐标系极角排序的应用(POJ1696)
    【进阶3-3期】深度广度解析 call 和 apply 原理、使用场景及实现(转)
    判断js数据类型的四种方法,以及各自的优缺点(转)
  • 原文地址:https://www.cnblogs.com/mollnn/p/13599869.html
Copyright © 2011-2022 走看看