zoukankan      html  css  js  c++  java
  • 题解 LOJ6669 【Nauuo and Binary Tree】

    题目链接

    Solution Nauuo and Binary Tree

    题目大意:有一棵 (n) 个节点的二叉树,根节点为 (1),你可以通过询问两个点之间简单路径的距离来还原这棵树,(nleq 3000),询问次数上限 (30000)

    树剖,交互


    分析:首先询问出所有点的深度,一层一层扩展。

    加入一个点后就暴力树剖一次,从 (1) 号点开始,每次询问当前点和重链底的距离,求出 (LCA) 的深度,如果没有找到父亲,就跳到 (LCA) 的轻儿子继续找。

    #include <cstdio>
    #include <vector>
    using namespace std;
    const int maxn = 3333;
    int faz[maxn],dfn[maxn],top[maxn],siz[maxn],son[maxn],dep[maxn],dfs_tot,n;
    vector<int> G[maxn],vec[maxn],chain[maxn];
    inline void addedge(int u,int v){
    	G[u].push_back(v);
    	faz[v] = u;
    }
    inline void dfs1(int u){
    	dfn[u] = ++dfs_tot;
    	siz[u] = 1;
    	son[u] = 0;
    	for(int v : G[u]){
    		if(v == faz[u])continue;
    		dep[v] = dep[u] + 1;
    		faz[v] = u;
    		dfs1(v);
    		siz[u] += siz[v];
    		if(siz[v] > siz[son[u]])son[u] = v;
    	}
    }
    inline void dfs2(int u,int tp){
    	chain[tp].push_back(u);
    	top[u] = tp;
    	if(son[u])dfs2(son[u],tp);
    	for(int v : G[u]){
    		if(v == faz[u] || v == son[u])continue;
    		dfs2(v,v);
    	}
    }
    inline void build(){
    	dfs_tot = 0;
    	for(int i = 1;i <= n;i++)chain[i].clear();
    	dfs1(1);
    	dfs2(1,1);
    }
    inline int query(int u,int v){
    	printf("? %d %d
    ",u,v);
    	fflush(stdout);
    	int res = 0;
    	scanf("%d",&res);
    	return res;
    }
    inline void out(){
    	printf("! ");
    	for(int i = 2;i <= n;i++)printf("%d ",faz[i]);
    	printf("
    ");
    	fflush(stdout);
    }
    int main(){
    	dep[1] = 1;
    	scanf("%d",&n);
    	vec[1].push_back(1);
    	for(int i = 2;i <= n;i++)
    		vec[query(1,i) + 1].push_back(i);
    	for(int x : vec[2])
    		addedge(1,x);
    	build();
    	for(int i = 3;!vec[i].empty();i++)
    		for(int x : vec[i]){
    			int now = 1;
    			while(true){
    				int dis = query(chain[top[now]].back(),x);
    				if(dis == 1){
    					addedge(chain[top[now]].back(),x);
    					build();
    					break;
    				}
    				int dl = (dep[chain[top[now]].back()] + i - dis) >> 1;
    				int lca = chain[top[now]][dl - dep[chain[top[now]].front()]];
    				if(G[lca].size() < 2){
    					addedge(lca,x);
    					build();
    					break;
    				}
    				for(int v : G[lca])
    					if(v != son[lca]){
    						now = v;
    						break;
    					}
    			}
    		}
    	out();
    	return 0;
    }
    
  • 相关阅读:
    Fruit HDU
    排列组合 HDU
    XOR and Favorite Number CodeForces
    BZOJ-6-2460: [BeiJing2011]元素-线性基
    CDH 安装与部署
    Apache Hadoop集群搭建
    大数据架构与技术选型
    项目落实方案选择思考(KUDU)
    JAVA 高级篇
    大数据就业岗位
  • 原文地址:https://www.cnblogs.com/colazcy/p/13873185.html
Copyright © 2011-2022 走看看