笛卡尔树是一种treap,她有两种权值:key和val。
1. 对于key权值,她有二叉搜索树的性质。
2. 对于val权值,她有大顶堆的性质。
因此我们可以对key排序之后,每次建树插入新节点就只需要考虑树上靠右的那条链即可。
每次插入一个新节点,我们找到链上靠近叶子节点的,第一个val大于她的节点,插在她的右子部分即可。
我们可以维护一个单调栈来完成这个操作,易知栈顶元素靠近叶子节点,栈底元素为根,且栈中元素key和val都分别具有单调性。
ZOJ2243
友情提示:此题的key是一个字符串。
#include <bits/stdc++.h>
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long LL;
int n;
char *str = "";
struct Descartes {
char key[110];
int val;
int l, r;
bool operator < (const Descartes & rhs) const {
return strcmp(key, rhs.key) < 0;
}
};
stack<int> stk;
vector<Descartes> V(50010);
void ins(int i) {
while(!stk.empty() && V[stk.top()].val < V[i].val) stk.pop();
int f = stk.top();
V[i].l = V[f].r;
V[f].r = i;
stk.push(i);
}
void dfs(int u) {
if(u == -1) return ;
printf("(");
dfs(V[u].l);
printf("%s/%d", V[u].key, V[u].val);
dfs(V[u].r);
printf(")");
}
int main() {
while(~scanf("%d", &n) && n) {
while(!stk.empty()) stk.pop();
V.clear();
V[0].val = 1000000000; V[0].l = V[0].r = -1;
for(int i = 1; i <= n; i++) {
scanf(" %[a-z]/%d", V[i].key, &V[i].val);
V[i].l = V[i].r = -1;
}
stk.push(0);
sort(V.begin() + 1, V.begin() + 1 + n);
for(int i = 1; i <= n; i++)
ins(i);
dfs(V[0].r);
puts("");
}
return 0;
}