zoukankan      html  css  js  c++  java
  • 学习笛卡尔树

    笛卡尔树(知识总结+板子整理)

    笛卡尔树

    例题1:hdu-6305

    RMQ Similar Sequence

    【题意】:

    题意:定义RMQ(A,l,r)为:序列A中,满足A[i] = max(A[l],A[l+1],...,A[r])的最小的i。如果对于任意(l,r)都满足RMQ(A,l,r)=RMQ(B,l,r)则为A和B是RMQ Similar。现在出A序列,B序列的每个数都是0~1之间的实数,问满足与A是RMQ Similar的所有B序列中所有数之和的期望。

    题解:不难看出如果A和B是RMQ Similar,则A和B的笛卡尔树同构。考虑B中的每个数是0~1之间的实数,因此出现相同数字的概率为0,可以假设B是每个数都不相同排列。设A的笛卡尔树每个子树的大小为sz[u],则任一B排列与A同构的概率是,因为B中每个数满足均匀分布,因此期望值为1/2,和的期望为n/2,因此满足与A同构的B中所有数之和的期望为


    所以求:sz[i] 指的是笛卡尔树每个子树的大小。

    贴上代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<stack>
     4 using namespace std;
     5 typedef long long ll;
     6 const int N = 1e6 + 5 ;
     7 const int INF = 0x3f3f3f3f;
     8 const int mod = 1e9+7;
     9 inline int read(){
    10     int x = 0 , f = 1 ;
    11     char c = getchar();
    12     while ( c < '0' || c > '9' ) {
    13         if( c=='-' ) f = -1 ;
    14         c = getchar();
    15     }
    16     while ( '0' <= c && c <= '9' ){
    17         x = x*10 + c-'0';
    18         c = getchar();
    19     }
    20     return x * f ;
    21 }
    22 typedef struct Node{
    23     int val,fa,sz;
    24     int L,R;
    25     Node(){}
    26 }Node;
    27 Node t[N];
    28 stack<int>st;
    29 void Init(int n){
    30     for(int i=0;i<=n;i++){
    31         t[i].sz = t[i].L = t[i].R = t[i].fa = 0;
    32     }
    33     t[0].val = INF;
    34     while(!st.empty()) st.pop();
    35     st.push(0);
    36 }
    37 
    38 void build(int n){
    39     int k ;
    40     for(int i=1;i<=n;i++){
    41         while( !st.empty() && t[st.top()].val < t[i].val )
    42             st.pop();
    43         k = st.top();
    44         t[i].L = t[k].R;
    45         t[k].R = i ;
    46         t[i].fa = k;
    47         t[t[i].L].fa = i ;
    48         st.push(i);
    49     }
    50 }
    51 void dfs(int u) {
    52     if ( !u ) return ;
    53     t[u].sz = 1 ;
    54     dfs( t[u].L );
    55     dfs( t[u].R );
    56     t[u].sz += t[t[u].L].sz
    57             + t[t[u].R].sz ;
    58 }
    59 ll inv[N];
    60 void Init() {
    61     inv[1] = 1;
    62     for (int i = 2; i < N; i++)
    63         inv[i] = inv[mod % i] * (mod - mod / i) % mod;
    64 }
    65 int main()
    66 {
    67     int T,n;
    68     Init();
    69     for ( scanf("%d",&T) ; T ; T-- ){
    70 
    71         n = read();
    72         Init(n);
    73         for(int i=1;i<=n;i++){
    74             t[i].val = read() ;
    75         }
    76         //puts("####");
    77 
    78         build(n);
    79         dfs(t[0].R);
    80 
    81         ll ans=n *inv[2]%mod;
    82         for(int i=1;i<=n;i++)
    83             ans=ans*inv[t[i].sz]%mod;
    84 
    85         printf("%lld
    ",ans);
    86     }
    87     return 0;
    88 }
    89 /*
    90 3
    91 3
    92 1 2 3
    93 3
    94 1 2 1
    95 5
    96 1 2 3 2 1
    97 */
    hdu-6305

    【例题2】poj-2201

    Cartesian Tree

    题目大意:裸的笛卡尔树,建树输出每个点的父节点和儿子节点编号,没有为0。

    构造一颗笛卡尔树,然后输出这棵树即可。

    首先进行排序,然后用一个栈维护最右的树的节点信息,插入的时候按照第二关键字去找,找到之后插入,下面的树成为它的左子树即可。

    然后插入分三种情况讨论(最下面,中间,成为了新的树根)

    题目分析:注意这题肯定要输出YES,因为给的每一对关键字都不相同,所以能建唯一的笛卡尔树,不存在NO的情况。还有排序后序号就乱了,注意一下就行了,其他的没什么了。
     1 #include<cstdio>
     2 #include<algorithm>
     3 const int N = 5e4+5;
     4 using namespace std;
     5 typedef struct Node{
     6     int id , L , R , val , key ,fa ;
     7     bool operator < (const Node &rhs )const {
     8         return key < rhs.key ;
     9     }
    10 }Node ;
    11 Node t[N];
    12 int n,L[N],R[N],st[N],Fa[N];
    13 void build(){
    14     int top = 0 ;
    15     st[top] = 1 ;
    16     for(int i=2;i<=n;i++){
    17         while( top >= 0 && t[st[top]].val > t[i].val )
    18             top -- ;
    19         if ( top > -1  ){
    20             t[i].L = t[st[top]].R;
    21             t[st[top]].R = i ;
    22             t[i].fa = st[top];
    23             t[t[i].L].fa = i ;
    24         }else{
    25             t[st[0]].fa = i ;
    26             t[i].L = st[0];
    27         }
    28         st[++top] =  i ;
    29     }
    30 }
    31 
    32 int main()
    33 {
    34     while(~scanf("%d",&n)){
    35         for(int i=1;i<=n;i++){
    36             scanf("%d%d",&t[i].key,&t[i].val);
    37             t[i].id = i ;
    38             t[i].L = t[i].R = t[i].fa = 0 ;
    39         }
    40         sort( t+1 , t+1+n ) ;
    41         build();
    42         for(int i=1;i<=n;i++){
    43             Fa[t[i].id] = t[t[i].fa].id;
    44             L[t[i].id] = t[t[i].L].id ;
    45             R[t[i].id] = t[t[i].R].id ;
    46         }
    47         puts("YES");
    48         for(int i=1;i<=n;i++){
    49             printf("%d %d %d
    ",Fa[i],L[i],R[i]);
    50         }
    51     }
    52     return 0;
    53 }
    54 /*
    55 
    56 7
    57 5 4
    58 2 2
    59 3 9
    60 0 5
    61 1 3
    62 6 6
    63 4 11
    64 
    65 YES
    66 2 3 6
    67 0 5 1
    68 1 0 7
    69 5 0 0
    70 2 4 0
    71 1 0 0
    72 3 0 0
    73  */
    poj - 2201
  • 相关阅读:
    BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊(分块)
    BZOJ 4241 历史研究(分块)
    BZOJ 3110 [Zjoi2013]K大数查询(整体二分)
    hdu 5412 CRB and Queries(整体二分)
    POJ2104 K-th Number(整体二分)
    luogu P3157 [CQOI2011]动态逆序对(CDQ分治)
    陌上开花(CDQ分治)
    BZOJ 1176[Balkan2007]Mokia(CDQ分治)
    BZOJ 3626 LCA(离线+树链剖分+差分)
    bzoj1592 Making the Grade
  • 原文地址:https://www.cnblogs.com/Osea/p/11216662.html
Copyright © 2011-2022 走看看