题目:

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1243
http://poj.org/problem?id=1785

题意:

给一个数n,然后有n对形如label/priority的二元组,用这n对二元组建一个treap,对label满足二叉搜索树的性质,对priority满足堆的性质,然后按(<left sub−treap><label>/<priority><right sub−treap>)的形式输出,即中序遍历这棵树,加一些括号

思路:

直接建treap肯定可以卡到O(n2),所以可以选择笛卡尔树,先对label排序,然后直接建笛卡尔树,然后中序遍历即可

#include <bits/stdc++.h>

using namespace std;

const int N = 50000 + 10, INF = INT_MAX;

struct node
{
    char val[100+10];
    int pri, fat, son[2];
    friend bool operator< (node a, node b)
    {
        if(strcmp(a.val, b.val) < 0) return true;
        else return false;
    }
    void init(int _pri, int _fat)
    {
        pri = _pri, fat = _fat;
        son[0] = son[1] = 0;
    }
}tr[N];

int root;
int top, stk[N];
int cartesian_build(int n)
{
    top = 0;
    for(int i = 1; i <= n; i++)
    {
        int k = top;
        while(k > 0 && tr[stk[k-1]].pri < tr[i].pri) k--;
        if(k != 0)
        {
            tr[stk[k-1]].son[1] = i;
            tr[i].fat = stk[k-1];
        }
        if(k != top)
        {
            tr[i].son[0] = stk[k];
            tr[stk[k]].fat = i;
        }
        stk[k++] = i;
        top = k;
    }
    return stk[0];
}
void dfs(int x)
{
    if(! x) return;
    printf("(");
    dfs(tr[x].son[0]);
    printf("%s/%d", tr[x].val, tr[x].pri);
    dfs(tr[x].son[1]);
    printf(")");
}
int main()
{
    int n;
    while(scanf("%d", &n), n)
    {
        tr[0].init(INF, 0);
        for(int i = 1; i <= n; i++)
        {
            scanf(" %[a-z]/%d", tr[i].val, &tr[i].pri);//这个读入比较有意思
            tr[i].init(tr[i].pri, 0);
        }
        sort(tr + 1, tr + 1 + n);
        root = cartesian_build(n);
        dfs(root);
        printf("\n");
    }
    return 0;
}

另外这题用单调栈也可以做。首先对label排序,然后按priority往左右扩展,扩展到不大于它的地方,加上括号即可。跟HDU1506正好一反,代码懒得写了。。。