• LOJ6669 Nauuo and Binary Tree


    说在前面的话

    这是一道很有意思的题,巧妙利用了树剖的性质,出题人有点东西的。

    题解

    这道题我们需要利用轻重链剖分的性质,做到一次塞点复杂度只有 (O(log_2n))

    首先比较显然的,我们肯定是要查出每一个点到达根节点的距离来预先得到一个塞点顺序,这样就保证了每一个点塞入的时候其祖先节点都已经在了。

    然后我们考虑询问。可以得到,我们每一次询问实际上是可以得到这个点与另一个点 ( ext{lca}) 的深度的,在我们已经知道了每一个点深度的情况下。

    这样我们就可以这么设计询问:每一次在移动完轻边后查询当前节点重链低端的点和塞入点的 ( ext{lca}) 的深度,如此我们就可以轻易得到下一次跳轻边的位置(因为是二叉树),然后重复上述步骤就可以了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=3e3+5;
    int n,fa[N];
    struct Node{int id,dep,size,son[2],bot;}tr[N];//0 is heavy
    bool cmp(const Node a,const Node b){return a.dep<b.dep;}
    void work(int rt,int u,int goal){
    	tr[rt].size++;
    	// printf("%d %d %d %d
    ",tr[rt].id,tr[u].id,now,goal);
    	// printf("%d %d %d
    ",tr[rt].son[0],tr[rt].son[1],tr[rt].bot);
    	if(tr[rt].dep>goal){
    		if(!tr[rt].son[0]){
    			tr[rt].son[0]=tr[rt].bot=u;
    			fa[tr[u].id]=tr[rt].id;
    			return ;
    		}
    		int dis;
    		printf("? %d %d
    ",tr[tr[rt].bot].id,tr[u].id);
    		fflush(stdout),scanf("%d",&dis);
    		goal=(tr[tr[rt].bot].dep+tr[u].dep-dis)/2;
    	}
    	if(tr[rt].dep==goal){
    		if(!tr[rt].son[0]){
    			tr[rt].son[0]=tr[rt].bot=u;
    			fa[tr[u].id]=tr[rt].id;
    			return ;
    		}
    		if(!tr[rt].son[1]){
    			tr[rt].son[1]=u;
    			fa[tr[u].id]=tr[rt].id;
    			return ;
    		}
    		work(tr[rt].son[1],u,goal);
    		if(tr[tr[rt].son[1]].size>tr[tr[rt].son[0]].size)
    		swap(tr[rt].son[0],tr[rt].son[1]);
    		tr[rt].bot=tr[tr[rt].son[0]].bot;
    		return ;
    	}
    	work(tr[rt].son[0],u,goal);
    	tr[rt].bot=tr[tr[rt].son[0]].bot;
    }
    int main(){
    	cin>>n;
    	for(int i=1;i<=n;++i) tr[i].id=i;
    	for(int i=2;i<=n;++i){
    		printf("? %d %d
    ",1,i);
    		fflush(stdout),scanf("%d",&tr[i].dep);
    	}
    	sort(tr+2,tr+1+n,cmp);
    	for(int i=1;i<=n;++i) tr[i].size=1,tr[i].bot=i;
    	for(int i=2;i<=n;++i) work(1,i,-1);
    	printf("!");
    	for(int i=2;i<=n;++i) printf(" %d",fa[i]);
    	return printf("
    "),0;
    }
    
  • 相关阅读:
    敏捷的调试
    敏捷的编码
    敏捷的需求分析
    敏捷的反馈
    敏捷的方法论
    敏捷的世界观
    MarkDown添加数学公式
    性能分析初学者指南
    可执行文件的装载与进程
    会话技术------客户端技术cookie
  • 原文地址:https://www.cnblogs.com/Point-King/p/14432877.html
Copyright © 2020-2023  润新知