• [LOJ 6669] Nauuo and Binary Tree


    一、题目

    点此看题

    二、解法

    注意到 (nleq 3000),那么对于 (30000) 次询问的理解方式就是用 (log) 次确定一个点的父亲。

    不难想到把所有点按深度分层,对于所有点求出和 (1) 的距离即可。

    我们考虑每做一次询问就要把父亲的范围缩小一半,因为二叉树本身就带有这种分治的功能,我们考虑从 (1) 开始确定,每次走左右儿子。但是因为题目给的二叉树可能形态迥异,所以暴力走是不行的。

    这变成一个优化结构问题了,我们要保证原树的形态所以点分治之类的技巧是行不通的,但树链剖分是一个很好的结构,我们可以只走轻边来保证复杂度。

    如何实现只走轻边?我们把重链底段的节点和待确定节点问一下距离,如果为 (1) 那么找到了父亲;否则可以反解出它们的 ( t lca) 深度,进而找到它们的 ( t lca),那么答案一定在重链的反方向,我们沿着这条轻边往下走即可。

    因为每次只用对深度前 (i) 的节点树剖,所以 (30000) 的询问次数绰绰有余。

    三、总结

    对结构的理解很重要,二叉树本身就是一种分治结构,优化结构的方法也很重要。

    //higher and higher , chase it
    #include <cstdio>
    #include <vector>
    using namespace std;
    const int M = 3005;
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,tot,f[M],d[M],ch[M][2],fa[M],dw[M],siz[M];
    vector<int> v[M];
    int ask(int u,int v)
    {
    	printf("? %d %d
    ",u,v);
    	fflush(stdout);
    	return read();
    }
    void dfs(int u)
    {
    	if(!u) return ;
    	siz[u]=1;
    	dfs(ch[u][0]);dfs(ch[u][1]);
    	siz[u]+=siz[ch[u][0]]+siz[ch[u][1]];
    	if(siz[ch[u][0]]>siz[ch[u][1]])
    		dw[u]=dw[ch[u][0]];
    	else dw[u]=dw[ch[u][1]];
    	if(siz[u]==1) dw[u]=u;
    }
    signed main()
    {
    	n=read();
    	for(int i=2;i<=n;i++)
    	{
    		d[i]=ask(1,i);
    		v[d[i]].push_back(i);
    	}
    	for(int i=1;i<=n;i++)
    	{
    		dfs(1);
    		for(auto u:v[i])
    		{
    			int x=1;
    			while(d[x]!=i-1)
    			{
    				int y=dw[x],t=(d[y]+d[u]-ask(y,u))/2;
    				t=d[y]-t;while(t--) y=fa[y];
    				if(d[y]==i-1) {x=y;break;}
    				if(siz[ch[y][0]]>siz[ch[y][1]])
    					x=ch[y][1];
    				else x=ch[y][0];
    			}
    			fa[u]=x;ch[x][ch[x][0]?1:0]=u;
    		}
    	}
    	printf("!");
    	for(int i=2;i<=n;i++)
    		printf(" %d",fa[i]);
    	puts("");
    	fflush(stdout);
    }
    
  • 相关阅读:
    10.6比赛 T1
    10.5比赛 T3
    10.5比赛 T2
    10.5比赛 T1
    最大子序列问题
    Python编程快速上手_第 4 章 列表
    Python编程快速上手_第 3 章 函数
    Python编程快速上手_第 2 章 控制流
    Python编程快速上手_第 1 章 Python基础
    Python 编程快速上手 ——让繁琐工作自动化
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/15326159.html
Copyright © 2020-2023  润新知