codility: upsilon2012 (Cartesian Sequence)

今天看了个很有趣的东西,叫笛卡尔树

Solution to this task can be found at our blog.

A non-empty zero-indexed array A consisting of N different integers is given. We are looking for the longest possible sequence built from elements of A, A[B[0]], A[B[1]], ..., A[B[K]], satisfying the following conditions:

  • The sequence must be decreasing; that is, A[B[0]] > A[B[1]] > ... > A[B[K]].
  • For any two consecutive elements of the sequence, A[B[I]] and A[B[I+1]], all the elements of A between them must be smaller than them; that is, for any J = MIN(B[I], B[I+1]) + 1, ..., MAX(B[I], B[I+1]) − 1, we have A[J] < A[B[I+1]].

Write a function:

int solution(const vector<int> &A);

that, given a zero-indexed array A containing N different integers, computes the maximum length of a sequence satisfying the above conditions.

For example, for the following array A:

 

  A[0]  =  9   A[1]  = 10   A[2]  =  2
  A[3]  = -1   A[4]  =  3   A[5]  = -5
  A[6]  =  0   A[7]  = -3   A[8]  =  1
  A[9]  = 12   A[10] =  5   A[11] =  8
  A[12] = -2   A[13] =  6   A[14] =  4

the function should return 6.
A sequence of length 6 satisfying the given conditions can be as follows:

 

  A[9] = 12    A[1] = 10    A[4] =  3
  A[8] =  1    A[6] =  0    A[7] = -3

Assume that:

  • the elements of A are all distinct;
  • N is an integer within the range [1..100,000];
  • each element of array A is an integer within the range [−1,000,000,000..1,000,000,000].

Complexity:

  • expected worst-case time complexity is O(N);
  • expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).

笛卡尔树是这么组织的,可以看成每个节点都包含有key,value两个值。如果只看key,那么这个树是个二叉搜索树;如果只看value,那么这个树是个大根堆(当然也可以是小根的)。然后这道题如果用了笛卡尔树的话那结果刚好是树的高度+1.

以题目中的例子来看:

树的节点上的数字是vector数组的序号i,括号里是值A[i]。从序号的角度来看,这是个二叉搜索树。但是如果看括号里的值,那它又是个大根堆。而题目中需要找的是A[B[0]] > A[B[1]] > ... > A[B[K]]. 因为是大根堆,所以从根节点(9(12))到 叶子节点7(-3)一定A[i]是递减的。然后A[B[I]] and A[B[I+1]]中间的元素必须要小于A[B[I+1]]。这一点也很好办,因为这个树从标号上来看是个二叉搜索树,所以标号B[i]和B[I+1]之间的节点必然在节点B[I+1]的左子树里,又因为它是个大根堆,所以肯定比A[B[I+1]]要小。好了两个条件都满足了,所以只要找到这个树最深的那条路径就是答案了。

代码参考了http://codesays.com/2014/solution-to-upsilon2012-cartesian-sequence-by-codility/

// you can also use includes, for example:
#include <algorithm>
#include <vector>
struct treeNode {
    int data;
    int height;
    treeNode *parent;
    treeNode *left;
    treeNode *right;
    treeNode(int data):data(data),height(0),parent(NULL),left(NULL),right(NULL) {}
};
int solution(const vector<int> &A) {
    // write your code in C++98
    if(A.size()==0)
        return 0;
    treeNode *root = new treeNode(A[0]);
    treeNode *prev = root;
    for(int i=1;i<A.size();i++) {
        treeNode *cur = new treeNode(A[i]);
        while(prev->data<=cur->data) {
            if(prev->left!=NULL) {
                prev->height = max(prev->left->height+1,prev->height);
            }
            if(prev->right!=NULL) {
                prev->height = max(prev->right->height+1,prev->height);
            }
            if(prev->parent==NULL) {
                cur->height = prev->height+1;
                cur->left = prev;
                prev->parent = cur;
                root = cur;
                break;
            }
            prev = prev->parent;
        }
        if(prev->data>cur->data) {
            cur->left = prev->right;
            cur->parent = prev;
            if(cur->left!=NULL) {
                cur->left->parent = cur;
                cur->height = cur->left->height+1;
            }
            prev->right = cur;
        }
        prev = cur;
    }
    while(prev->parent!=NULL) {
        prev = prev->parent;
        prev->height = max(prev->height,prev->right->height+1);
    }
    return root->height+1;
}

 

 

 

转载于:https://www.cnblogs.com/parapax/p/3664723.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值