给出一些结点
每个节点有两个关键字
要求构造一棵树
第一个关键字满足二叉搜索树的性质,第二个关键字满足小堆的性质
解题思路:这道题我开始是用第二关键字从小到大排序,然后从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; }