给出一些结点
每个节点有两个关键字
要求构造一棵树
第一个关键字满足二叉搜索树的性质,第二个关键字满足小堆的性质
解题思路:这道题我开始是用第二关键字从小到大排序,然后从1-n去添加节点。这样是符合最小堆的性质,假设添加第i个节点,那么首先去找[1,i-1]这段区间的第一关键字的最小值和最大值,如果i节点的第一关键字大于最大值,就直接添加到最大值节点的右儿子,如果小于最小值,就添加到最小值节点的左儿子,否则就直接从根节点往下找。可是超时了,其实超时的原因还蛮明显的,因为你添加的i节点不一定每次都是大于最大值,小于最小值,更多的情况可能是在中间值,这样每次都要从根节点出发往下走,这样就会造成遍历的时间太多了。但按照这种思路,很难直接找到i节点的父节点是谁,因为[1,i-1]区间内的第一关键字是无序的。
参考了网上的思路,绝大部分都是按照第一关键字排序,然后再去找区间段内的最小值作为子树的根节点。
http://blog.csdn.net/sdj222555/article/details/7909198
我的TLE:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 50005;
struct Node
{
int k,a;
int id;
bool operator < (const Node &T)
{
return a < T.a;
}
}tree[maxn];
struct Result
{
int parent,left,right;
}res[maxn];
int n,value[maxn],dp_max[maxn][20],dp_min[maxn][20];
int _max(int l,int r)
{
if(tree[l].k > tree[r].k) return l;
return r;
}
int _min(int l,int r)
{
if(tree[l].k < tree[r].k) return l;
return r;
}
void initRMQ()
{
for(int i = 1; i <= n; i++)
dp_max[i][0] = dp_min[i][0] = i;
for(int j = 1; (1 << j) <= n; j++)
for(int i = 1; i + (1 << j) - 1 <= n; i++)
{
dp_max[i][j] = _max(dp_max[i][j-1],dp_max[i+(1<<j-1)][j-1]);
dp_min[i][j] = _min(dp_min[i][j-1],dp_min[i+(1<<j-1)][j-1]);
}
}
int MaxValue(int l,int r)
{
int k = (int)(log((r - l + 1)*1.0) / log(2.0));
return _max(dp_max[l][k],dp_max[r-(1<<k)+1][k]);
}
int MinValue(int l,int r)
{
int k = (int)(log((r - l + 1)*1.0) / log(2.0));
return _min(dp_min[l][k],dp_min[r-(1<<k)+1][k]);
}
void Build()
{
int maxm,minm;
for(int i = 1; i <= n; i++)
res[i].parent = res[i].left = res[i].right = 0;
for(int i = 2; i <= n; i++)
{
maxm = MaxValue(1,i-1);
minm = MinValue(1,i-1);
if(tree[i].k > tree[maxm].k)
{
res[tree[maxm].id].right = tree[i].id;
res[tree[i].id].parent = tree[maxm].id;
}
else if(tree[i].k < tree[minm].k)
{
res[tree[minm].id].left = tree[i].id;
res[tree[i].id].parent = tree[minm].id;
}
else
{
int p = tree[1].id;
while(true)
{
if(tree[i].k > value[p])
{
if(res[p].right != 0)
p = res[p].right;
else
{
res[p].right = tree[i].id;
res[tree[i].id].parent = p;
break;
}
}
else
{
if(res[p].left != 0)
p = res[p].left;
else
{
res[p].left = tree[i].id;
res[tree[i].id].parent = p;
break;
}
}
}
}
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i = 1; i <= n; i++)
{
scanf("%d%d",&tree[i].k,&tree[i].a);
tree[i].id = i;
value[i] = tree[i].k;
}
sort(tree+1,tree+1+n);
initRMQ();
Build();
printf("YES\n");
for(int i = 1; i <= n; i++)
printf("%d %d %d\n",res[i].parent,res[i].left,res[i].right);
}
return 0;
}