bzoj 2770 堆的中序遍历性质
我们知道二叉搜索树的中序遍历是一个已经排好序的序列,知道序列我们无法确定树的形态(因为有多种)。
但是,Treap如果告诉我们它的关键字以及权值,那么就可以唯一确定树的形态(Treap的O(logn)的期望时间复杂度就是依靠一个随机堆的深度不会太深)
具体的,已知关键字序列:k1,k2,k3...kn和优先级序列:p1,p2,p3,...pn,
如果我们想要找ki的父亲,只需要找“左边第一个p比它大的和右边第一个p比它大的中,p较小的那个“
至于lca(ki,kj),是对应的pi~pj中的最小值(因为是小根堆)
至于深度,多次找父亲,路径长度就是深度,然后画一下图可以发现轨迹的特点,然后就可以搞了(求两段递增子序列长度)
1 /************************************************************** 2 Problem: 2770 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:6140 ms 7 Memory:46124 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <vector> 12 #include <algorithm> 13 #define oo 0x6FFFFFFF 14 #define maxn 400010 15 using namespace std; 16 17 typedef pair<int,int> dpr; 18 19 struct Node { 20 int lf, rg, mid; 21 dpr st; 22 bool leaf; 23 Node *ls, *rs; 24 } pool[maxn*3], *tail=pool, *root; 25 vector<Node*> stk; 26 27 int disc[maxn], ntot; 28 int sv[maxn]; 29 int pr[maxn][3]; 30 31 Node *build( int lf, int rg ) { 32 Node *nd = ++tail; 33 nd->lf=lf, nd->rg=rg, nd->mid=(lf+rg)>>1; 34 if( lf==rg ) { 35 nd->st = dpr( oo, 0 ); 36 nd->leaf = true; 37 } else { 38 nd->ls = build( lf, nd->mid ); 39 nd->rs = build( nd->mid+1, rg ); 40 nd->st = dpr( oo, 0 ); 41 nd->leaf = false; 42 } 43 return nd; 44 } 45 dpr qu_min( Node *nd, int lf, int rg ) { 46 if( lf <= nd->lf && nd->rg <= rg ) return nd->st; 47 dpr rt = dpr( oo, 0 ); 48 if( lf <= nd->mid ) 49 rt = qu_min( nd->ls, lf, rg ); 50 if( rg > nd->mid ) 51 rt = min( rt, qu_min( nd->rs, lf, rg ) ); 52 return rt; 53 } 54 void pushup( Node *nd ) { 55 nd->st = min( nd->ls->st, nd->rs->st ); 56 } 57 void modify( Node *nd, int pos, int val ) { 58 if( nd->leaf ) { 59 nd->st = dpr( val, pos ); 60 return; 61 } 62 if( pos <= nd->mid ) 63 modify( nd->ls, pos, val ); 64 else 65 modify( nd->rs, pos, val ); 66 pushup( nd ); 67 } 68 int lca( int u, int v ) { 69 if( u>v ) swap(u,v); 70 return qu_min( root, u, v ).second; 71 } 72 73 int main() { 74 int n, m, T; 75 scanf( "%d%d", &n, &m ); 76 T = n+m; 77 for( int i=1; i<=n; i++ ) { 78 pr[i][0] = 0; 79 scanf( "%d", pr[i]+1 ); 80 disc[++ntot] = pr[i][1]; 81 } 82 for( int i=1; i<=n; i++ ) 83 scanf( "%d", pr[i]+2 ); 84 for( int i=n+1; i<=T; i++ ) { 85 char opt[10]; 86 scanf( "%s", opt ); 87 pr[i][0] = opt[0]=='I' ? 0 : 88 opt[0]=='D' ? 1 : 2; 89 if( pr[i][0]==0 ) { 90 scanf( "%d%d", pr[i]+1, pr[i]+2 ); 91 disc[++ntot] = pr[i][1]; 92 } else if( pr[i][0]==1 ) { 93 scanf( "%d", pr[i]+1 ); 94 } else { 95 scanf( "%d%d", pr[i]+1, pr[i]+2 ); 96 } 97 } 98 sort( disc+1, disc+1+ntot ); 99 ntot = unique( disc+1, disc+1+ntot ) - disc - 1; 100 for( int i=1; i<=T; i++ ) { 101 pr[i][1] = lower_bound( disc+1, disc+1+ntot, pr[i][1] )-disc; 102 if( pr[i][0]==2 ) 103 pr[i][2] = lower_bound( disc+1, disc+1+ntot, pr[i][2] )-disc; 104 } 105 root = build( 1, ntot ); 106 for( int i=1; i<=T; i++ ) { 107 if( pr[i][0]==0 ) { 108 modify( root, pr[i][1], pr[i][2] ); 109 } else if( pr[i][0]==1 ) { 110 modify( root, pr[i][1], oo ); 111 } else { 112 int u = pr[i][1]; 113 int v = pr[i][2]; 114 printf( "%d\n", disc[lca(u,v)] ); 115 } 116 } 117 }