zoukankan      html  css  js  c++  java
  • bzoj3173 Splay 维护前缀中的最大值

    大致题意:

    有一个空序列,依次插入1~N到该序列中,每次指定插入的位置,每次插入完成返回当前序列的LIS的长度。

    题解:

    设dp[i]表示 前缀1~i的最长上升子序列的长度。

    因为是按照递增顺序插入的,所以当刚插入完某个数到i位置(此时能保证该数是当前序列的最大值)dp[i] = max{ dp[j] | j<i },答案 ans=max{ dp[i] | i in [1,len] }

    因为要支持动态插入,所以要用BST来做,每个节点代表一个位置(即树的中序遍历就是该序列),每个节点维护dp[i]和 dpmax[i] = max{ dp[i] | i in the subtree }

    代码:

      1 #include <cstdio>
      2 #include <iostream>
      3 #define maxn 100010
      4 using namespace std;
      5 
      6 struct Splay {
      7     int pre[maxn], son[maxn][2], siz[maxn], ntot, root;
      8     int dp[maxn], dmax[maxn];
      9 
     10     Splay() {
     11         root = ntot = 0;
     12     }
     13     void update( int nd ) {
     14         siz[nd] = siz[son[nd][0]] + siz[son[nd][1]] + 1;
     15         dmax[nd] = max( dp[nd], max( dmax[son[nd][0]], dmax[son[nd][1]] ) );
     16     }
     17     void rotate( int nd, int d ) {
     18         int p = pre[nd];
     19         int s = son[nd][!d];
     20         int ss = son[s][d];
     21         
     22         son[nd][!d] = ss;
     23         son[s][d] = nd;
     24         if( !p ) root = s;
     25         else son[p][ nd==son[p][1] ] = s;
     26 
     27         pre[s] = p;
     28         pre[nd] = s;
     29         if( ss ) pre[ss] = nd;
     30 
     31         update(nd);
     32         update(s);
     33     }
     34     void splay( int nd, int top ) {
     35         while( pre[nd]!=top ) {
     36             int p = pre[nd];
     37             if( pre[p]==top ) {
     38                 rotate( p, son[p][0]==nd );
     39             } else {
     40                 int pp = pre[p];
     41                 int pl = p == son[pp][0];
     42                 int nl = nd == son[p][0];
     43                 if( pl==nl ) {
     44                     rotate( pp, pl );
     45                     rotate( p, nl );
     46                 } else {
     47                     rotate( p, nl );
     48                     rotate( pp, pl );
     49                 }
     50             }
     51         }
     52     }
     53     int find( int pos ) {    //    pos in [1,sz]
     54         int nd = root;
     55         while(1) {
     56             int ls = siz[son[nd][0]];
     57             if( pos<=ls ) {
     58                 nd = son[nd][0];
     59             } else if( pos>=ls+2 ) {
     60                 nd = son[nd][1];
     61                 pos -= ls+1;
     62             } else {
     63                 return nd;
     64             }
     65         }
     66     }
     67     int premax( int pos ) {
     68         int nd = root;
     69         int rt = 0;
     70         while(1) {
     71             int ls = siz[son[nd][0]];
     72             if( pos<=ls ) {
     73                 nd = son[nd][0];
     74             } else if( pos>=ls+2 ) {
     75                 rt = max( rt, max( dp[nd], dmax[son[nd][0]] ) );
     76                 nd = son[nd][1];
     77                 pos -= ls+1;
     78             } else {
     79                 rt = max( rt, max( dp[nd], dmax[son[nd][0]] ) );
     80                 break;
     81             }
     82         }
     83         return rt;
     84     }
     85     int newnode( int p, int v ) {
     86         int nd = ++ntot;
     87         pre[nd] = p;
     88         son[nd][0] = son[nd][1] = 0;
     89         siz[nd] = 1;
     90         dp[nd] = dmax[nd] = v;
     91         return nd;
     92     }
     93     void insert( int pos ) {
     94         if( !root ) {
     95             root = newnode( 0, 1 );
     96             return;
     97         }
     98         if( pos==0 ) {
     99             int nd = root;
    100             while( son[nd][0] ) nd=son[nd][0];
    101             son[nd][0] = newnode( nd, 1 );
    102             update( nd );
    103             splay( nd, 0 );
    104             return;
    105         }
    106         int nd = find( pos );
    107         int nw = newnode( nd,premax(pos)+1 );
    108         int s = son[nd][1];
    109         son[nd][1] = nw;
    110         son[nw][1] = s;
    111         pre[nw] = nd;
    112         if( s ) pre[s] = nw;
    113         update( son[nd][1] );
    114         update( nd );
    115         splay( nd, 0 );
    116     }
    117     void print( int nd ) {
    118         if( !nd ) return;
    119         print( son[nd][0] );
    120         printf( "%d(%d,%d,%d,%d,%d) ", dp[nd], nd, pre[nd], son[nd][0], son[nd][1], nd==son[pre[nd]][0] );
    121         print( son[nd][1] );
    122     }
    123 };
    124 
    125 Splay T;
    126 int n;
    127 int main() {
    128     //freopen( "input", "r", stdin );
    129     scanf( "%d", &n );
    130     for( int i=1,pos; i<=n; i++ ) {
    131         scanf( "%d", &pos );
    132         T.insert( pos );
    133 //        T.print(T.root);
    134 //        printf( "
    " );
    135         printf( "%d
    ", T.dmax[T.root] );
    136     }
    137 }
  • 相关阅读:
    python中用exit退出程序
    习题5-2 使用函数求奇数和 (15分)
    习题5-1 符号函数 (10分)
    练习5-3 数字金字塔 (15分)
    练习5-2 找两个数中最大者 (10分)
    练习5-1 求m到n之和 (10分)
    ubuntu使用教程
    图解HTTP 上
    Sublime Text 3 插件
    两千行PHP学习笔记
  • 原文地址:https://www.cnblogs.com/idy002/p/4273283.html
Copyright © 2011-2022 走看看