二叉搜索树上的LCA(最近公共祖先)
2017-05-05 18:05
375 查看
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, eachline 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 中间,则直接返回mid
ll 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;
}
相关文章推荐
- 树上两点的最近公共祖先-Tarjan_LCA离线算法
- 树上倍增方法求LCA(最近公共祖先)(转)
- 树上两点的最近公共祖先-Tarjan_LCA离线算法
- 中石油5909: 货物运输(LCA树上两点最近公共祖先) SDWC 2018 day5
- 树上倍增求LCA(最近公共祖先)
- 树上倍增求LCA(最近公共祖先)
- 二叉搜索数求最近公共祖先
- 最近公共祖先(LCA)之树上倍增法
- 最近公共祖先LCA:RMQ转化
- LCA最近公共祖先问题(Tarjan离线算法)
- LCA(最近公共祖先)
- 洛谷P3379 【模板】最近公共祖先(LCA)
- LCA----【模板】最近公共祖先(LCA)
- CodeVs.2370 小机房的树 ( LCA 倍增 最近公共祖先)
- LCA(Least Common Ancestors)最近公共祖先
- 最近公共祖先问题(LCA)
- 洛谷P3379 【模板】最近公共祖先(LCA)(树链剖分)
- 用“倍增法”求最近公共祖先(LCA)
- c++最近公共祖先LCA(倍增算法和tarjan)
- LCA(least common ancestors)最近公共祖先