您的位置:首页 > 其它

【 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 :

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: