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 }