• 单调栈求笛卡尔树


    笛卡尔树实际上是对一个整数序列建树,以这个整数序列为优先级,下标为数,建Treap

    当优先级互不相同,笛卡尔树是惟一的

    笛卡尔树可以通过区间rmq并维护一个位置在 O(n log n) 的时间内求出来,不过我们有 O(n) 的做法

    我们用一个单调栈维护当前优先级递减的序列,然后不断弹栈找到合适位置,把最后一个弹走的元素的父亲标记为她,再把她的父亲标记为栈顶就行

    【题目描述】
    Treap 是一种平衡二叉搜索树,除二叉搜索树的基本性质外,Treap 还满足一个性质:
    每个节点都有一个确定的优先级,且每个节点的优先级都比它的两个儿子小(即它的优先级满足堆性质)。
    不难证明在节点的优先级都事先给定且互不相同时,对应的 Treap 有且仅有一个。
    现在,给定 n 个数和每个数对应的优先级,求出对应的以数的大小作为二叉搜索树比较依据的 Treap 的先序遍历结果。
    对先序遍历的定义是:先访问根节点,再访问左子树,最后访问右子树。
    【输入格式】
    第一行一个数 n 表示数的个数。
    第二行 n 个数表示每个数的大小。
    第三行 n 个数表示每个数对应的优先级。
    【输出各式】
    一行 n 个数,表示 Treap 的先序遍历结果(对于每个节点,输出对应的数)。
    
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    struct data { int val, pri; } a[100010];
    int n, fa[100010], s[100010], lc[100010], rc[100010], top;
    
    void dfs(int x)
    {
    	printf("%d ", a[x].val);
    	if (lc[x]) dfs(lc[x]);
    	if (rc[x]) dfs(rc[x]);
    }
    
    int main()
    {
    	scanf("%d", &n);
    	for (int i = 1; i <= n; i++) scanf("%d", &a[i].val);
    	for (int i = 1; i <= n; i++) scanf("%d", &a[i].pri), a[i].pri = -a[i].pri;
    	sort(a + 1, a + 1 + n, [](const data &a, const data &b) { return a.val < b.val; });
    	s[top = 1] = 1;
    	for (int i = 2; i <= n; i++)
    	{
    		if (a[i].pri > a[s[top]].pri)
    		{
    			while (top > 0 && a[i].pri > a[s[top]].pri) top--;
    			fa[s[top + 1]] = i;
    		}
    		fa[i] = s[top], s[++top] = i;
    	}
    	for (int i = 1; i <= n; i++) if (fa[i])
    	{
    		if (fa[i] > i) lc[fa[i]] = i;
    		else if (fa[i] < i) rc[fa[i]] = i;
    	}
    	for (int i = 1; i <= n; i++) if (fa[i] == 0) dfs(i);
    	return 0;
    }
    
  • 相关阅读:
    计算机英语
    NSQ学习记录
    Java学习记录-注解
    VS插件开发

    双链表
    顺序表
    顺序队列
    顺序栈

  • 原文地址:https://www.cnblogs.com/oier/p/10615325.html
Copyright © 2020-2023  润新知