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
", disc[lca(u,v)] );
115         }
116     }
117 }
View Code
原文地址:https://www.cnblogs.com/idy002/p/4316514.html