poj 2201(RMQ+笛卡尔树)

来源:互联网 发布:知乎周刊一共多少期 编辑:程序博客网 时间:2024/05/29 12:12

给出一些结点

每个节点有两个关键字

要求构造一棵树

第一个关键字满足二叉搜索树的性质,第二个关键字满足小堆的性质


解题思路:这道题我开始是用第二关键字从小到大排序,然后从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;}


0 0
原创粉丝点击