二叉搜索树上的LCA(最近公共祖先)

来源:互联网 发布:2017 unity3d开发语言 编辑:程序博客网 时间:2024/05/16 01:27

1017: Easy Tree Query

时间限制: 3 Sec  内存限制: 128 MB
提交: 184  解决: 30
[提交][状态][讨论版]

题目描述

You are given a binary search tree with depth k, whose nodes are valued from 1 to (2k − 1) and then Q queries.
For each query, you are given p nodes. Find the root of a smallest subtree which contains all p nodes and print its value.

输入

The first line of input contains an integer T (T ≤ 100), the number of test cases. The first line of each test case contains two integers k (1 ≤ k ≤ 60) and Q (1 ≤ Q ≤ 10 4 ). In next Q lines, each line contains an integer p and then p integers — the values of nodes in this query. It is guaranteed that the total number of nodes given in each test case will not exceed 105.

输出

For each query, print a line contains the answer of that query.

样例输入

1
4 1
3 10 15 13

样例输出

12


#include<cstdio>#include<algorithm>#include<map>#include<cstring>#include<vector>#include<queue>#include<set>#include<map>#include<cstdlib>#include<iostream>using namespace std;typedef long long ll;#define mem(a,x) memset(a,x,sizeof a)const int maxn = (int)1e5 + 5;int T,k,q,p;ll ans, aa[maxn];// 基本的递归查找,二分查找,//如果mid 比y大,说明x,y的父节点在当前树的左子树。// 如果mid 比 x 小,说明x,y的父节点在当前树的右子树。//一旦找到mid 在 x y 中间,则直接返回midll get_lca(ll l,ll r, ll x ,ll y){    if(x > y) swap(x,y);    ll mid = l + (r - l) / 2;    if(y < mid) return get_lca(l,mid-1,x,y);    if(x > mid) return get_lca(mid+1, r,x,y);    return mid;}int main(){    scanf("%d",&T);    while(T--){        scanf("%d %d",&k, &q);        while(q--){            scanf("%d",&p);            for(int i=1;i<=p;i++)                scanf("%lld",&aa[i]);            ans = aa[1];            ll n = (1ll << k)-1;            for(int i=2;i<=p;i++)                ans = get_lca(1,n,ans,aa[i]);            printf("%lld\n",ans);        }    }    return 0;}


比赛的时候想复杂了。通过将二叉搜索树上的值转化为二进制,然后找到了规律,每次都将当前的两个数转化为二进制,然后找到第一个不同的二进制位,先判断置为0可否,再判断了置为1可否。超时。

超时代码

#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#include<iostream>using namespace std;typedef long long ll;const int maxn = 1e5 + 10;ll arr[maxn];int n=4,m;ll getone(ll pre, ll old){    if(pre == old) return pre;    if(pre >old) swap(pre,old);    ll ppre = pre;    ll pold = old;    vector<int>v1;    vector<int>v2;    while(pre){        v1.push_back(pre%2);        pre>>=1;    }    while(old){        v2.push_back(old%2);        old>>=1;    }    while(v1.size() < n) v1.push_back(0);    while(v2.size() < n) v2.push_back(0); //    reverse(v1.begin(),v1.end());//    reverse(v2.begin(),v2.end());    ll ans = 0;    int k = n-1;////        for(int i=0;i<v1.size();i++)//        cout<<v1[i]<<" ";//    cout<<endl;//     for(int i=0;i<v2.size();i++)//        cout<<v2[i]<<" ";//    cout<<endl;     for(int i=n-1;i>=0;i--){        if(v1[i] != v2[i]){            if(ans >= ppre && ans<= pold){                return ans;            }else{                   ll ans1 = ans + (1<<k);                    return ans1;            }        }else{            if(v1[i] == 1)                ans += (1<<k);            k--;        }    }}int main(){    //cout<<getone(2,4)<<endl;    int T;scanf("%d",&T);    while(T--){        scanf("%d%d",&n,&m);        ll top  =  1<<(n-1);        int topn = n-1;        while(m--){            int q;scanf("%d",&q);            ll pre;            for(int i=0;i<q;i++){                scanf("%lld",&arr[i]);                if(i == 0) pre = arr[i];                else{                    pre = getone(pre,arr[i]);                }            }            printf("%lld\n",pre);        }    }    return 0;}


0 0