zoukankan      html  css  js  c++  java
  • 【学习笔记】笛卡尔树

    定义

    一棵树,每个点有两个权值,如果 (a) 权值满足 (BST)(b)权值满足 (heap),那么这棵树 就是一棵笛卡尔树

    一般是对于一个序列建笛卡尔树

    其实 (Treap) ,就是一个笛卡尔树,不过笛卡尔树不平衡

    性质

    一棵子树的中序遍历对应原序列中的一个区间

    构造

    (O(n)) 建树

    考虑用单调栈维护最右边的一条链(有点右偏树的意思??)

    然后每一次考虑对第二关键字进行单调相关的 (push) , (pop) 操作

    如果第二关键字遇到 (RMQ),了就 (break)

    随便理解吧

    代码:

    for(int i=1;i<=n;++i)
    {
    	while(top&&a[st[top]]>a[i]) ls[i]=st[top--];//或者别的RMQ
    	if(top) rs[st[top]]=i;
    	st[++top]=i;
    }
    

    合并

    定义关键点:一个树最左边和最右边两个链

    关键点只有初始的(O(n))个

    合并 (x,y) 时候,对于 (x) 的右链和 (y) 的左链,从最底下开始往上找到第一个能放的位置,这一段长度设为 (len)

    之后这段关键点会被覆盖住,不再存在。

    然后 (y) 的这个点左儿子和 (x) 的这个点的右儿子进行类似 (fhq) 的合并,也就是一般的暴力合并

    由于路径上的点就是两个段的关键点

    关键点然后就消失了。

    走的长度就是关键点减少的个数

    所以均摊(O(n))

    从最底下开始找,可以用链表然后链表合并。单纯记录每个点最右边的点也可以

    (size) 什么的(pushup)就找到了。

    (pushup) 这个不太好找到,最开始一段链很难搞。可以用 (LCT) 同时和笛卡尔树合并做,用于打上标记)

    直接搬的@(Miracle)的博客……理解力太差,真的没太懂(或者就是不会写)

    用途

    1.一堆矩形,底贡献,高度不同,求一个最大的子矩形,使得高度和宽度的乘积最大

    直接对序列建笛卡尔树,然后对于子树的(size) 和高度求乘积就好

    正确性显然(因为 (size) 就是宽度)

    这题显然可以考虑单调栈啥的((NOIP2013) 积木大赛)

    2.SP3734

    我们看到这个是一个直方图,而且形状不规则,就考虑到建一棵笛卡尔树

    然后把题目转成在矩形中选点(笛卡尔树把直方图变成一个一个的矩形,然后就是放点了)

    这里有个结论:(n imes m) 的矩形中我们放 (k) 点,方案数为:(C^{k}_n imes C^k_m imes k space !)

    每个点都占一行和一列,所以两个组合数的乘积就是一个组合,排列数直接乘阶乘就好

    然后是笛卡尔树上的 (dp), 这里转移就考虑枚举在每一岔上放几个点就行了,最后加一加,乘一乘

  • 相关阅读:
    论文阅读 | Adversarial Example Generation with Syntactically Controlled Paraphrase Networks
    Textual Entailment(自然语言推理-文本蕴含)
    论文阅读 | Probing Neural Network Understanding of Natural Language Arguments
    BiLSTM-CRF模型理解
    论文阅读 | Text Processing Like Humans Do: Visually Attacking and Shielding NLP Systems
    论文阅读 | Universal Adversarial Triggers for Attacking and Analyzing NLP
    QA 中的对抗攻击和防御
    2010 年 10 年前的网文【我的10年计算机之路】
    IntelliJ 的搜索和全局搜索怎么用
    Spring Data 的 Pivotal GemFire 参考指南前言
  • 原文地址:https://www.cnblogs.com/yspm/p/12384859.html
Copyright © 2011-2022 走看看