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( "\n" );
135         printf( "%d\n", T.dmax[T.root] );
136     }
137 }

 

posted @ 2015-02-04 21:20  idy002  阅读(370)  评论(0编辑  收藏  举报