642 字
3 分钟
COGS 2421 简单的Treap
【题目描述】
Treap是一种平衡二叉搜索树,除二叉搜索树的基本性质外,Treap还满足一个性质: 每个节点都有一个确定的优先级,且每个节点的优先级都比它的两个儿子小(即它的优先级满足堆性质)。 不难证明在节点的优先级都事先给定且互不相同时,对应的Treap有且仅有一个。 现在,给定n个数和每个数对应的优先级,求出对应的以数的大小作为二叉搜索树比较依据的Treap的先序遍历结果。 对先序遍历的定义是:先访问根节点,再访问左子树,最后访问右子树。
【输入格式】
第一行一个数n表示数的个数。 第二行n个数表示每个数的大小。 第三行n个数表示每个数对应的优先级。
【输出格式】
一行n个数,表示Treap的先序遍历结果(对于每个节点,输出对应的数)。
【样例输入】
7
2 11 5 9 1 4 3
2 10 1 8 4 6 5
【样例输出】
5 2 1 3 4 9 11
【样例解释】
对应的Treap如图所示,其中圈内的数是给出的数,圈外的数是节点的优先级。
【数据范围】
n<=500000。 所有的数和优先级都互不相同且在int(C++)/longint(Pascal)范围内。
【提示】
为了给不想用栈模拟递归的孩纸们偷懒的机会,C++选手请在main函数的开头加入以下代码:
int __size__=128<<20;
char *__p__=(char*)malloc(__size__)+__size__;
__asm__("movl %0, %%esp\n"::"r"(__p__));
注意上述代码会占用你128MB的空间,请自行调整代码。
题解
其实就是排序后用笛卡尔树建一颗树
所以这道题是一道笛卡尔树的裸题
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
class data
{
public:
int v, key;
bool operator<(const data &a) const
{
return v < a.v;
}
} a[500005];
class Node
{
public:
Node *ch[2];
int key, v;
Node(data x)
{
key = x.key;
v = x.v;
ch[0] = ch[1] = NULL;
}
~Node();
} * st[500005];
Node *build(int m)
{
Node *x, *last;
int p = 0;
for (int i = 1; i <= m; i++)
{
x = new Node(a[i]);
last = NULL;
while (p && st[p]->key > x->key)
{
last = st[p];
st[p--] = NULL;
}
if (p)
st[p]->ch[1] = x;
x->ch[0] = last;
st[++p] = x;
}
return st[1];
}
void dfs(Node *a)
{
if (a)
{
printf("%d ", a->v);
dfs(a->ch[0]);
dfs(a->ch[1]);
}
}
int main()
{
int __size__ = 128 << 20;
char *__p__ = (char *)malloc(__size__) + __size__;
__asm__("movl %0, %%esp\n" ::"r"(__p__));
freopen("treap.in","r",stdin);
freopen("treap.out","w",stdout);
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i].v);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i].key);
sort(a + 1, a + n + 1);
Node *rt = build(n);
dfs(rt);
}