• LOJ #6669 Nauuo and Binary Tree (交互题、树链剖分)


    题目链接

    https://loj.ac/problem/6669

    题解

    Orz yyf太神了,出这种又有意思又有意义的好题造福人类……
    首先(n)次询问求出所有节点的深度。
    考虑按深度扩展(BFS), 同时维护重链剖分
    每次扩展一个点时,从根节点所在重链开始,每次询问当前节点与链底节点的距离,这样就可以算出它们LCA的深度,也就是当前节点到根的路径上与这条重链相交部分的最大深度。那么如果这个最大深度等于当前深度(-1), 就得到了该点的父亲;否则跳到LCA的轻儿子所在重链上,继续询问即可。
    时间复杂度(O(n^2)), 询问次数(O(nlog n)).

    代码

    比我想象中的好写一些。

    #include<bits/stdc++.h>
    #define llong long long
    using namespace std;
    
    inline int read()
    {
    	int x = 0,f = 1; char ch = getchar();
    	for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}
    	for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}
    	return x*f;
    }
    
    const int N = 3000;
    int son[N+3][2];
    int hvs[N+3];
    int dep[N+3];
    int fa[N+3];
    int sz[N+3];
    vector<int> idep[N+3];
    int n;
    
    int getbtn(int u) {while(son[u][hvs[u]]) {u = son[u][hvs[u]];} return u;}
    int jumpup(int u,int x) {while(x--) {u = fa[u];} return u;}
    int jumpdown(int u,int x) {while(x--) {u = son[u][hvs[u]];} return u;}
    void verify(int u) {hvs[u] = (sz[son[u][1]]>sz[son[u][0]]);}
    void setfa(int u,int v) //fa[u]=v
    {
    //	printf("setfa %d %d
    ",u,v);
    	fa[u] = v; sz[u] = 1; son[v][son[v][0]?1:0] = u;
    	while(v)
    	{
    		verify(v); sz[v]++; v = fa[v];
    	}
    }
    
    void work(int u)
    {
    	int v = getbtn(1);
    	while(1)
    	{
    		printf("? %d %d
    ",v,u); fflush(stdout);
    		int dis; scanf("%d",&dis);
    		int deplca = (dep[u]+dep[v]-dis)>>1;
    		v = jumpup(v,dep[v]-deplca);
    		if(dep[u]-deplca==1) {setfa(u,v); return;}
    		v = son[v][hvs[v]^1]; v = getbtn(v);
    	}
    }
    
    int main()
    {
    	scanf("%d",&n);
    	for(int i=2; i<=n; i++) {printf("? %d %d
    ",1,i); fflush(stdout); scanf("%d",&dep[i]); idep[dep[i]].push_back(i);}
    	for(int i=0; i<idep[1].size(); i++) {setfa(idep[1][i],1);}
    	for(int i=2; i<=n; i++)
    	{
    		for(int j=0; j<idep[i].size(); j++)
    		{
    			int u = idep[i][j];
    			work(u);
    		}
    	}
    	printf("! "); for(int i=2; i<=n; i++) printf("%d ",fa[i]); puts(""); fflush(stdout);
    	return 0;
    }
    
  • 相关阅读:
    Android Animations动画使用详解
    android LinearLayout和RelativeLayout实现精确布局
    中国天气网API
    获取中央气象台API 完整城市列表简单方式
    Django框架 连接Oracle -ServerName方式报错
    关于java的动态代理
    Mybatis缓存
    Git使用,将本地项目推送到GitHub上
    使用doxc4j将word转pdf遇到的一个问题
    linux安装jdk
  • 原文地址:https://www.cnblogs.com/suncongbo/p/12070871.html
Copyright © 2020-2023  润新知