【 bzoj 3065 】 带插入区间K小值 - 树套树乱搞
2016-02-04 01:00
281 查看
这题写的真是excited。。。
虽然树套树这种东西随便嘴巴嘴巴就会了。。。但是写起来还是十分的蛋疼。。。
下午四点左右开始写,到将近七点写完,然后吃饭+思考人生了一小时,又开始debug,将近十二点时过对拍,洗了发澡冷静了一下,然后轰炸评测机= =十二点半左右时AC。
最后发现是因为线段树值域开小了。。。orz。。。
带插入带修改的区间K小值是有很多做法的,然后我看VFK给的标算都太好写了(大雾),然后搞了一个十分奇怪的做法。。。
首先用一棵重量平衡树维护当前的序列,同时维护任意两个位置对应节点的先后顺序(就是重量平衡树的经典应用),我用了Scapegoat Tree = =
然后开一棵权值线段树,每个节点维护的是对应权值区间所有元素的位置的平衡树,这些平衡树里面每个元素的大小就是外面那棵重量平衡树所对应的先后顺序。
这样插入的话就先在重量平衡树上插一下,接着在值域线段树里面一路跑下去,顺路往平衡树里面插当前位置。
修改就先把对应位置的元素在树套树里删掉,然后再插入(略暴力,但是没想到别的更好的做法)。
查询的话就是主席树思想,在线段树上看看左区间那棵平衡树里对应区间的元素个数有多少个,然后按方向走下去。
因为有重量平衡树快速维护了任意两个节点之间的大小关系,所以插入和修改都是O(log2n)的,查询显然也是O(log2n)的。因为要提取一段区间出来,所以线段树套的那棵平衡树要能支持提取区间,我写的是非旋转Treap = =
这样总时间复杂度差不多就是O(qlog2n)咯。
贴两份代码吧。。。一份是调试的时候加了各种奇怪的东西的代码。。。一份是最终交的代码。。。
码力++
Final Code :
Debug Code :
虽然树套树这种东西随便嘴巴嘴巴就会了。。。但是写起来还是十分的蛋疼。。。
下午四点左右开始写,到将近七点写完,然后吃饭+思考人生了一小时,又开始debug,将近十二点时过对拍,洗了发澡冷静了一下,然后轰炸评测机= =十二点半左右时AC。
最后发现是因为线段树值域开小了。。。orz。。。
带插入带修改的区间K小值是有很多做法的,然后我看VFK给的标算都太好写了(大雾),然后搞了一个十分奇怪的做法。。。
首先用一棵重量平衡树维护当前的序列,同时维护任意两个位置对应节点的先后顺序(就是重量平衡树的经典应用),我用了Scapegoat Tree = =
然后开一棵权值线段树,每个节点维护的是对应权值区间所有元素的位置的平衡树,这些平衡树里面每个元素的大小就是外面那棵重量平衡树所对应的先后顺序。
这样插入的话就先在重量平衡树上插一下,接着在值域线段树里面一路跑下去,顺路往平衡树里面插当前位置。
修改就先把对应位置的元素在树套树里删掉,然后再插入(略暴力,但是没想到别的更好的做法)。
查询的话就是主席树思想,在线段树上看看左区间那棵平衡树里对应区间的元素个数有多少个,然后按方向走下去。
因为有重量平衡树快速维护了任意两个节点之间的大小关系,所以插入和修改都是O(log2n)的,查询显然也是O(log2n)的。因为要提取一段区间出来,所以线段树套的那棵平衡树要能支持提取区间,我写的是非旋转Treap = =
这样总时间复杂度差不多就是O(qlog2n)咯。
贴两份代码吧。。。一份是调试的时候加了各种奇怪的东西的代码。。。一份是最终交的代码。。。
码力++
Final Code :
#include <bits/stdc++.h> using namespace std; #define rep(i,a,b) for (int i = a , _ = b ; i <= _ ; i ++) #define per(i,a,b) for (int i = a , _ = b ; i >= _ ; i --) const int maxn = 1000007; const int maxs = 600007; inline int rd() { char c = getchar(); while (!isdigit(c)) c = getchar() ; int x = c - '0'; while (isdigit(c = getchar())) x = x * 10 + c - '0'; return x; } inline int rnd () { static int rand_seed = 18230742; rand_seed += rand_seed << 1 | 1; return rand_seed; } inline void upmax ( int &a , int b ) { if ( a < b ) a = b; } inline void upmin ( int &a , int b ) { if ( a > b ) a = b; } int n , a[maxn]; int node_tot; namespace ScapeTree { const double alpha = 0.75; struct node { node *l , *r , *fa; double tag_l , tag_r; int sz , key , val; node ( int _key = 0 , int _val = 0 ): key (_key) , val (_val) { l = r = fa = NULL , tag_l = tag_r = 0 , sz = 1; } inline double mid () { return ( tag_l + tag_r ) / 2; } inline void upd_sz () { sz = 1; if (l) sz += l->sz; if (r) sz += r->sz; } }; node *pos[maxn] , *rt; int travel_key[maxn] , travel_val[maxn] , travel_cnt; int v , ins_val; inline int Size ( node *u ) { return u == NULL ? 0 : u -> sz; } node *BuildTree ( int *_key , int *_val , int l , int r , node *p = NULL ) { if ( l > r ) return NULL; int m = (l + r) >> 1 ; node *u = new node ( _key[m] , _val[m] ); u->fa = p; pos[_key[m]] = u; u -> l = BuildTree ( _key , _val , l , m - 1 , u ); u -> r = BuildTree ( _key , _val , m + 1 , r , u ); u -> upd_sz (); return u; } void upd_tag ( node *u ) { double tag_m = ( u->tag_l + u->tag_r ) / 2; node *l = u->l , *r = u->r; if (l) l->tag_l = u->tag_l , l->tag_r = tag_m , upd_tag (l); if (r) r->tag_r = u->tag_r , r->tag_l = tag_m , upd_tag (r); } inline node *build ( int *_key , int *_val , int n , double l , double r ) { node *rt = BuildTree ( _key , _val , 1 , n ); rt -> tag_l = l , rt -> tag_r = r; upd_tag ( rt ); return rt; } void travel ( node *u ) { if (!u) return; travel (u->l); travel_key[++ travel_cnt] = u->key; travel_val[ travel_cnt] = u->val; travel (u->r); delete u; } inline void init ( int *a , int n ) { rep ( i , 1 , n ) travel_key[i] = i , travel_val[i] = a[i]; rt = build ( travel_key , travel_val , n , -1e9 , 1e9 ); ::node_tot = n; } inline node *get_rank ( int k ) { node *u = rt; for ( ;; ) { int t = Size ( u->l ) + 1; if ( t == k ) return u; else if ( t < k ) k -= t , u = u->r; else u = u->l; } } inline node *insert_before_node ( node* u ) { node *goat = NULL; if ( u -> l ) { if ( u->l->sz + 1 > u->sz * alpha ) goat = u; for ( u = u->l , u->sz ++ ; u->r ; u = u->r , u->sz ++ ) { if ( goat == NULL && u->r->sz + 1 > u->sz * alpha ) goat = u; } u->r = new node ( v , ins_val ); node *x = u->r; pos[v] = x , x->fa = u; x->tag_r = u->tag_r; x->tag_l = u->mid(); } else { u->l = new node ( v , ins_val ); node *x = u->l; pos[v] = x , x->fa = u; x->tag_l = u->tag_l; x->tag_r = u->mid(); } return goat; } inline node *insert_before_k ( node* u , int k ) { int cur_size = Size ( u->l ) + 1; u->sz ++; if ( cur_size == k ) { return insert_before_node (u); } node *goat = NULL; if ( cur_size < k ) { if ( u->r == NULL ) { u->r = new node ( v , ins_val ); node *x = u->r; pos[v] = x , x->fa = u; x->tag_r = u->tag_r; x->tag_l = u->mid(); return NULL; } goat = insert_before_k ( u->r , k - cur_size ); if ( u->r->sz > u->sz * alpha ) goat = u; } else { if ( u->l == NULL ) { u->l = new node ( v , ins_val ); node *x = u->l; pos[v] = x , x->fa = u; x->tag_l = u->tag_l; x->tag_r = u->mid(); return NULL; } goat = insert_before_k ( u->l , k ); if ( u->l->sz > u->sz * alpha ) goat = u; } return goat; } void insert_before_k ( int pos , int k , int _val ) { v = pos , ins_val = _val; node *goat = insert_before_k ( rt , k ); if ( goat == NULL ) return; double t_l = goat->tag_l , t_r = goat->tag_r , t_m = ( t_l + t_r ) / 2; node *p = goat->fa; travel_cnt = 0; travel (goat); goat = build ( travel_key , travel_val , travel_cnt , t_l , t_r ); if (p) { if ( t_m > p->mid () ) p->r = goat; else p->l = goat; goat->fa = p; } } } struct pos_info { int x; pos_info ( int _x = 0 ): x (_x) { } inline pos_info operator= ( int x ) { this -> x = x; return *this; } inline friend bool operator< ( pos_info a , pos_info b ) { return ScapeTree::pos[a.x]->mid () < ScapeTree::pos[b.x]->mid (); } inline friend bool operator<= ( pos_info a , pos_info b ) { return a.x == b.x || a < b; } inline friend bool operator== ( pos_info a , pos_info b ) { return a.x == b.x; } }; #define fir first #define sec second list <int> table[maxn]; struct TreapNode { TreapNode *l , *r; int pri , sz; pos_info key; TreapNode ( pos_info _key = 0 ): key (_key) , pri (rnd ()) , sz (1) { l = r = NULL ; } inline void upd () { sz = 1; if (l) sz += l->sz; if (r) sz += r->sz; } }; TreapNode *mem_pool[maxn] , data_pool[maxs * 30]; int mem_top , data_top; inline TreapNode *newnode ( pos_info v ) { TreapNode *u; if ( mem_top ) u = mem_pool[mem_top --]; else u = &data_pool[data_top ++]; *u = TreapNode ( pos_info (v) ); return u; } inline void delnode ( TreapNode *u ) { mem_pool[++ mem_top] = u; } typedef pair <TreapNode* , TreapNode*> Droot; TreapNode *join ( TreapNode *u , TreapNode *v ) { if ( u == NULL ) return v; if ( v == NULL ) return u; if ( u->pri < v->pri ) { u->r = join ( u->r , v ); u->upd(); return u; } else { v->l = join ( u , v->l ); v->upd(); return v; } } Droot split ( TreapNode *u , pos_info pos ) // put value no more than pos into left , else in right { if ( u == NULL ) return Droot ( NULL , NULL ); Droot t; if ( u->key <= pos ) { t = split ( u->r , pos ); u->r = t.fir , t.fir = u; } else { t = split ( u->l , pos ); u->l = t.sec , t.sec = u; } u->upd(); return t; } inline TreapNode *build_treap ( list <int> &a ) { static TreapNode *stack[maxn] , *pre , *u; int top = 0; stack[1] = NULL; for ( list <int> :: iterator it = a.begin () ; it != a.end () ; it ++ ) { u = newnode( pos_info(*it) ); pre = NULL; while ( top && stack[top]->pri > u->pri ) { stack[top] -> upd(); pre = stack[top --]; } if (top) stack[top] -> r = u; u -> l = pre; stack[++ top] = u; } while (top) stack[top --] -> upd (); return stack[1]; } inline int get_treap_size ( TreapNode* &u , pos_info l , pos_info r ) { if (!u) return 0; Droot t1 = split ( u , r ) , t2; if ( l.x != 0 ) t2 = split ( t1.fir , l ); else t2 = Droot ( NULL , t1.fir ); int ret = (t2.sec == NULL ? 0 : t2.sec->sz); u = join ( join ( t2.fir , t2.sec ) , t1.sec ); return ret; } inline void treap_insert ( TreapNode* &u , pos_info t ) { if ( u == NULL ) { u = newnode (t); return ; } Droot t1 = split ( u , t ); u = join ( join ( t1.fir , newnode (t) ) , t1.sec ); } inline void treap_erase ( TreapNode* &u , pos_info l , pos_info r ) { Droot t1 = split ( u , r ) , t2; if ( l.x != 0 ) t2 = split ( t1.fir , l ); else t2 = Droot ( NULL , t1.fir ); delnode ( t2.sec ); u = join ( t2.fir , t1.sec ); } int mx_val; inline void merge_list ( list <int>& a , list <int>& b , list <int>& c ) // c = a + b { list <int> :: iterator it_a = a.begin () , it_b = b.begin (); while ( it_a != a.end () && it_b != b.end () ) { if ( *it_a < *it_b ) c.push_back ( *it_a ) , it_a ++; else c.push_back ( *it_b ) , it_b ++; } for ( ; it_a != a.end () ; it_a ++ ) c.push_back ( *it_a ); for ( ; it_b != b.end () ; it_b ++ ) c.push_back ( *it_b ); a.clear () , b.clear (); } struct SegNode { list <int> lst; TreapNode *rt; SegNode *l , *r; SegNode () { l = r = NULL , rt = NULL , lst.clear (); } }SegNode_mem_pool[maxs]; int SegNode_mem_top; inline SegNode *new_SegNode () { return &SegNode_mem_pool[SegNode_mem_top ++]; } namespace SegTree { #define T SegNode* &u = rt , int l = 0 , int r = 70000 #define L u -> l , l , m #define R u -> r , m + 1 , r SegNode *rt; int ql , qr , k; pos_info _l , _r; void build_SegTree ( T ) { u = new_SegNode (); if ( l == r ) { u->lst = table[l]; u->rt = build_treap ( u->lst ); return ; } int m = ( l + r ) >> 1; build_SegTree (L) , build_SegTree (R); merge_list ( u -> l -> lst , u -> r -> lst , u -> lst ); u->rt = build_treap ( u->lst ); } int que (T) { if ( l == r ) return l; int t = get_treap_size ( u->l->rt , _l , _r ); int m = ( l + r ) >> 1; if ( t >= k ) return que (L); else { k -= t ; return que (R) ; } } void ins (T) { treap_insert ( u->rt , _l ); if ( l == r ) return ; int m = ( l + r ) >> 1; if ( ql <= m ) ins (L); else ins (R); } void del (T) { treap_erase ( u->rt , _l , _r ); if ( l == r ) return ; int m = ( l + r ) >> 1; if ( ql <= m ) del (L); else del (R); } void modi (T) { treap_insert ( u->rt , _r ); if ( l == r ) return ; int m = ( l + r ) >> 1; if ( ql <= m ) modi (L); else modi (R); } inline void init () { build_SegTree (); } inline int Q ( int l , int r , int _k ) { if ( l != 1 ) _l = ScapeTree::get_rank ( l - 1 )->key; else _l = 0; _r = ScapeTree::get_rank (r)->key; k = _k; return que (); } inline void M ( int p , int x ) { ScapeTree::node *t = ScapeTree::get_rank (p); if ( p != 1 ) _l = ScapeTree::get_rank( p - 1 ) -> key; else _l = 0; ql = t->val , _r = t->key; del (); ql = t->val = x; modi (); } inline void I ( int p , int x ) { ScapeTree::insert_before_k ( ++ node_tot , p , x ); _l = ScapeTree::pos[node_tot]->key; ql = x; ins (); } } void input () { n = rd (); rep ( i , 1 , n ) { a[i] = rd (); table[a[i]].push_back (i); upmax ( mx_val , a[i] ); } ScapeTree::init ( a , n ); SegTree::init (); } static int ans = 0; inline void query () { int l = rd () ^ ans , r = rd () ^ ans , k = rd () ^ ans; ans = SegTree::Q ( l , r , k ); printf ( "%d\n" , ans ); } inline void modify () { int p = rd() ^ ans , x = rd () ^ ans; SegTree::M ( p , x ); } inline void insert () { int p = rd () ^ ans , x = rd () ^ ans; SegTree::I ( p , x ); } inline char read_cmd () { char c = getchar (); while (!isalpha(c)) c = getchar (); return c; } void solve () { int q = rd (); rep ( i , 1 , q ) { char cmd = read_cmd (); switch (cmd) { case 'Q' : query () ; break ; case 'M' : modify() ; break ; case 'I' : insert() ; break ; } } } int main () { #ifndef ONLINE_JUDGE freopen("data.txt" , "r" , stdin); #endif input (); solve (); return 0; }
Debug Code :
#include <bits/stdc++.h> using namespace std; #define rep(i,a,b) for (int i = a , _ = b ; i <= _ ; i ++) #define per(i,a,b) for (int i = a , _ = b ; i >= _ ; i --) const int maxn = 150007; const int maxs = 300007; #define gprintf(...) //fprintf ( stderr , __VA_ARGS__ ) inline int rd() { char c = getchar(); while (!isdigit(c)) c = getchar() ; int x = c - '0'; while (isdigit(c = getchar())) x = x * 10 + c - '0'; return x; } inline int rnd () { static int rand_seed = 42071823; rand_seed += rand_seed << 1 | 1; return rand_seed; } inline void upmax ( int &a , int b ) { if ( a < b ) a = b; } inline void upmin ( int &a , int b ) { if ( a > b ) a = b; } int n , a[maxn]; int node_tot; namespace ScapeTree { const double alpha = 0.742; struct node { node *l , *r , *fa; double tag_l , tag_r; int sz , key , val; node ( int _key = 0 , int _val = 0 ): key (_key) , val (_val) { l = r = fa = NULL , tag_l = tag_r = 0 , sz = 1; } inline double mid () { return ( tag_l + tag_r ) / 2; } inline void upd_sz () { sz = 1; if (l) sz += l->sz; if (r) sz += r->sz; } }; node *pos[maxn] , *rt; int travel_key[maxn] , travel_val[maxn] , travel_cnt; int v , ins_val; inline int Size ( node *u ) { return u == NULL ? 0 : u -> sz; } node *BuildTree ( int *_key , int *_val , int l , int r , node *p = NULL ) { if ( l > r ) return NULL; int m = (l + r) >> 1 ; node *u = new node ( _key[m] , _val[m] ); u->fa = p; pos[_key[m]] = u; u -> l = BuildTree ( _key , _val , l , m - 1 , u ); u -> r = BuildTree ( _key , _val , m + 1 , r , u ); u -> upd_sz (); return u; } void upd_tag ( node *u ) { double tag_m = ( u->tag_l + u->tag_r ) / 2; node *l = u->l , *r = u->r; if (l) l->tag_l = u->tag_l , l->tag_r = tag_m , upd_tag (l); if (r) r->tag_r = u->tag_r , r->tag_l = tag_m , upd_tag (r); } inline node *build ( int *_key , int *_val , int n , double l , double r ) { node *rt = BuildTree ( _key , _val , 1 , n ); rt -> tag_l = l , rt -> tag_r = r; upd_tag ( rt ); return rt; } void travel ( node *u ) { if (!u) return; travel (u->l); travel_key[++ travel_cnt] = u->key; travel_val[ travel_cnt] = u->val; travel (u->r); delete u; } inline void init ( int *a , int n ) { rep ( i , 1 , n ) travel_key[i] = i , travel_val[i] = a[i]; rt = build ( travel_key , travel_val , n , 0 , 1e8 ); ::node_tot = n; } inline node *get_rank ( int k ) { node *u = rt; for ( ;; ) { int t = Size ( u->l ) + 1; if ( t == k ) return u; else if ( t < k ) k -= t , u = u->r; else u = u->l; } } inline node *insert_before_node ( node* u ) { node *goat = NULL; if ( u -> l ) { if ( u->l->sz + 1 > u->sz * alpha ) goat = u; for ( u = u->l , u->sz ++ ; u->r ; u = u->r , u->sz ++ ) { if ( goat == NULL && u->r->sz + 1 > u->sz * alpha ) goat = u; } u->r = new node ( v , ins_val ); node *x = u->r; pos[v] = x , x->fa = u; x->tag_r = u->tag_r; x->tag_l = u->mid(); } else { u->l = new node ( v , ins_val ); node *x = u->l; pos[v] = x , x->fa = u; x->tag_l = u->tag_l; x->tag_r = u->mid(); } return goat; } inline node *insert_before_k ( node* u , int k ) { int cur_size = Size ( u->l ) + 1; u->sz ++; if ( cur_size == k ) { return insert_before_node (u); } node *goat = NULL; if ( cur_size < k ) { if ( u->r == NULL ) { u->r = new node ( v , ins_val ); node *x = u->r; pos[v] = x , x->fa = u; x->tag_r = u->tag_r; x->tag_l = u->mid(); return NULL; } goat = insert_before_k ( u->r , k - cur_size ); if ( u->r->sz > u->sz * alpha ) goat = u; } else { if ( u->l == NULL ) { u->l = new node ( v , ins_val ); node *x = u->l; pos[v] = x , x->fa = u; x->tag_l = u->tag_l; x->tag_r = u->mid(); return NULL; } goat = insert_before_k ( u->l , k ); if ( u->l->sz > u->sz * alpha ) goat = u; } assert ( Size(u->l) + Size(u->r) + 1 == u->sz ); return goat; } void insert_before_k ( int pos , int k , int _val ) { v = pos , ins_val = _val; node *goat = insert_before_k ( rt , k ); if ( goat == NULL ) return; double t_l = goat->tag_l , t_r = goat->tag_r , t_m = ( t_l + t_r ) / 2; node *p = goat->fa; travel_cnt = 0; travel (goat); goat = build ( travel_key , travel_val , travel_cnt , t_l , t_r ); if (p) { if ( t_m > p->mid () ) p->r = goat; else p->l = goat; goat->fa = p; } } void dbg_travel ( node *u ) { if (!u) return; dbg_travel (u->l); gprintf ( "%d " , u->val ); assert ( Size(u->l) + Size(u->r) + 1 == u->sz ); dbg_travel (u->r); } void print () { dbg_travel (rt); if (rt != NULL) puts (""); } void size_travel ( node *u ) { if (!u) return; size_travel (u->l); assert ( Size(u->l) + Size(u->r) + 1 == u->sz ); size_travel (u->r); } void check_size () { size_travel (rt); } } struct pos_info { int x; pos_info ( int _x = 0 ): x (_x) { } inline pos_info operator= ( int x ) { this -> x = x; return *this; } inline friend bool operator< ( pos_info a , pos_info b ) { return ScapeTree::pos[a.x]->mid () < ScapeTree::pos[b.x]->mid (); } inline friend bool operator<= ( pos_info a , pos_info b ) { return a.x == b.x || a < b; } inline friend bool operator== ( pos_info a , pos_info b ) { return a.x == b.x; } }; #define fir first #define sec second list <int> table[maxn]; struct TreapNode { TreapNode *l , *r; int pri , sz; pos_info key; TreapNode ( pos_info _key = 0 ): key (_key) , pri (rnd ()) , sz (1) { l = r = NULL ; } inline void upd () { sz = 1; if (l) sz += l->sz; if (r) sz += r->sz; } }; void treap_travel ( TreapNode *u ) { if (!u) return; treap_travel (u->l); gprintf ( "%d " , ScapeTree::pos[u->key.x]->val ); treap_travel (u->r); } void treap_print ( TreapNode *u ) { #ifndef DEBUG return; #endif treap_travel (u); if ( u != NULL ) puts (""); } TreapNode *mem_pool[maxn] , data_pool[maxs * 30]; int mem_top , data_top; inline TreapNode *newnode ( pos_info v ) { TreapNode *u; if ( mem_top ) u = mem_pool[mem_top --]; else u = &data_pool[data_top ++]; *u = TreapNode ( pos_info (v) ); return u; } inline void delnode ( TreapNode *u ) { mem_pool[++ mem_top] = u; } typedef pair <TreapNode* , TreapNode*> Droot; TreapNode *join ( TreapNode *u , TreapNode *v ) { if ( u == NULL ) return v; if ( v == NULL ) return u; if ( u->pri < v->pri ) { u->r = join ( u->r , v ); u->upd(); return u; } else { v->l = join ( u , v->l ); v->upd(); return v; } } Droot split ( TreapNode *u , pos_info pos ) // put value no more than pos into left , else in right { if ( u == NULL ) return Droot ( NULL , NULL ); Droot t; if ( u->key <= pos ) { t = split ( u->r , pos ); u->r = t.fir , t.fir = u; } else { t = split ( u->l , pos ); u->l = t.sec , t.sec = u; } u->upd(); return t; } inline TreapNode *build_treap ( list <int> &a ) { static TreapNode *stack[maxn] , *pre , *u; int top = 0; stack[1] = NULL; for ( list <int> :: iterator it = a.begin () ; it != a.end () ; it ++ ) { u = newnode( pos_info(*it) ); pre = NULL; while ( top && stack[top]->pri > u->pri ) { stack[top] -> upd(); pre = stack[top --]; } if (top) stack[top] -> r = u; u -> l = pre; stack[++ top] = u; } while (top) stack[top --] -> upd (); return stack[1]; } inline int get_treap_size ( TreapNode* &u , pos_info l , pos_info r ) { if (!u) return 0; Droot t1 = split ( u , r ) , t2; if ( l.x != 0 ) t2 = split ( t1.fir , l ); else t2 = Droot ( NULL , t1.fir ); int ret = (t2.sec == NULL ? 0 : t2.sec->sz); u = join ( join ( t2.fir , t2.sec ) , t1.sec ); return ret; } inline void treap_insert ( TreapNode* &u , pos_info t ) { if ( u == NULL ) { u = newnode (t); return ; } Droot t1 = split ( u , t ); u = join ( join ( t1.fir , newnode (t) ) , t1.sec ); } inline void treap_erase ( TreapNode* &u , pos_info l , pos_info r ) { Droot t1 = split ( u , r ) , t2; // treap_print (t1.fir) , treap_print (t1.sec); if ( l.x != 0 ) t2 = split ( t1.fir , l ); else t2 = Droot ( NULL , t1.fir ); delnode ( t2.sec ); u = join ( t2.fir , t1.sec ); } int mx_val; inline void merge_list ( list <int>& a , list <int>& b , list <int>& c ) // c = a + b { list <int> :: iterator it_a = a.begin () , it_b = b.begin (); while ( it_a != a.end () && it_b != b.end () ) { if ( *it_a < *it_b ) c.push_back ( *it_a ) , it_a ++; else c.push_back ( *it_b ) , it_b ++; } for ( ; it_a != a.end () ; it_a ++ ) c.push_back ( *it_a ); for ( ; it_b != b.end () ; it_b ++ ) c.push_back ( *it_b ); a.clear () , b.clear (); } struct SegNode { list <int> lst; TreapNode *rt; SegNode *l , *r; SegNode () { l = r = NULL , rt = NULL , lst.clear (); } }SegNode_mem_pool[maxs]; int SegNode_mem_top; inline SegNode *new_SegNode () { return &SegNode_mem_pool[SegNode_mem_top ++]; } #ifdef DEBUG #define __SEG_TREAP__ \ {\ gprintf ( "current %d %d\n" , l , r );\ treap_print (u->rt);\ } #else #define __SEG_TREAP__ #endif namespace SegTree { #define T SegNode* &u = rt , int l = 0 , int r = 70000 #define L u -> l , l , m #define R u -> r , m + 1 , r SegNode *rt; int ql , qr , k; pos_info _l , _r; bool flag; void build_SegTree ( T ) { u = new_SegNode (); if ( l == r ) { u->lst = table[l]; u->rt = build_treap ( u->lst ); return ; } int m = ( l + r ) >> 1; build_SegTree (L) , build_SegTree (R); merge_list ( u -> l -> lst , u -> r -> lst , u -> lst ); u->rt = build_treap ( u->lst ); #ifdef DEBUG gprintf ( "range %d %d\n" , l , r ); for ( list<int>::iterator it = u->lst.begin () ; it != u->lst.end () ; it ++ ) gprintf ( "%d " , *it ); gprintf ("\n"); #endif } int que (T) { if ( l == r ) return l; int t = get_treap_size ( u->l->rt , _l , _r ); int m = ( l + r ) >> 1; if ( t >= k ) return que (L); else { k -= t ; return que (R) ; } } void ins (T) { treap_insert ( u->rt , _l ); __SEG_TREAP__ if ( l == r ) return ; int m = ( l + r ) >> 1; if ( ql <= m ) ins (L); else ins (R); } void del (T) { treap_erase ( u->rt , _l , _r ); __SEG_TREAP__ if ( l == r ) return ; int m = ( l + r ) >> 1; if ( ql <= m ) del (L); else del (R); } void modi (T) { treap_insert ( u->rt , _r ); __SEG_TREAP__ if ( l == r ) return ; int m = ( l + r ) >> 1; if ( ql <= m ) modi (L); else modi (R); } inline void init () { build_SegTree (); } inline int Q ( int l , int r , int _k ) { if ( l != 1 ) _l = ScapeTree::get_rank ( l - 1 )->key; else _l = 0; _r = ScapeTree::get_rank (r)->key; k = _k; return que (); } inline void M ( int p , int x ) { ScapeTree::node *t = ScapeTree::get_rank (p); if ( p != 1 ) _l = ScapeTree::get_rank( p - 1 ) -> key; else _l = 0; ql = t->val , _r = t->key; del (); ql = t->val = x; modi (); } inline void I ( int p , int x ) { ScapeTree::insert_before_k ( ++ node_tot , p , x ); _l = ScapeTree::pos[node_tot]->key; ql = x; ins (); } } void input () { n = rd (); rep ( i , 1 , n ) { a[i] = rd (); table[a[i]].push_back (i); upmax ( mx_val , a[i] ); } ScapeTree::init ( a , n ); SegTree::init (); } static int ans = 0; inline void query () { gprintf ( "query\n" ); int l = rd () ^ ans , r = rd () ^ ans , k = rd () ^ ans; ans = SegTree::Q ( l , r , k ); printf ( "%d\n" , ans ); } inline void modify () { gprintf ( "modify\n" ); int p = rd() ^ ans , x = rd () ^ ans; SegTree::M ( p , x ); } inline void insert () { gprintf ( "insert\n" ); int p = rd () ^ ans , x = rd () ^ ans; SegTree::I ( p , x ); } inline char read_cmd () { char c = getchar (); while (!isalpha(c)) c = getchar (); return c; } void solve () { int q = rd (); rep ( i , 1 , q ) { gprintf ( "%d\n" , i ); char cmd = read_cmd (); switch (cmd) { case 'Q' : query () ; break ; case 'M' : modify() ; break ; case 'I' : insert() ; break ; } #ifdef DEBUG gprintf ( "current list : " ); ScapeTree::print( ); #endif // ScapeTree::check_size (); } } int main () { // freopen("info.txt" , "w" , stderr); #ifndef ONLINE_JUDGE freopen("data.txt" , "r" , stdin); freopen("data.out" , "w" , stdout); #endif input (); solve (); return 0; }
相关文章推荐
- 在Ubuntu14.04下安装Redis
- redis翻译(1)
- 第一章·第一节·创世之旅——面向对象建模方法之一
- 数据结构图文解析之:树的简介及二叉排序树C++模板实现.
- [LeetCode]163. Missing Ranges
- 【题解】BUPT 2015 freshman contest 2
- 安卓智能指针
- overridePendingTransition
- spring IOC的理解
- 【Redis test】You need tcl 8.5 or newer in order to run the Redis test
- 两个任意长度的长整数相乘(C语言、双向链表方法)
- Android开发刷新相册问题!!
- WordPress优化:修改文章标签为彩色标签
- [html5]动态多边形flat-surface-shader
- 快过年了
- CentOS6.5下修改MySQL编码方法
- [LeetCode]162. Find Peak Element
- swap file "*.swp" already exists!的解决方法
- 自定义控件中如何实现按钮之间的共轭?
- 51Nod 1046 A^B Mod C(快速幂)