今天看了个很有趣的东西,叫笛卡尔树
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; }