【 bzoj 3065 】 带插入区间K小值 - 树套树乱搞

5 篇文章 0 订阅
2 篇文章 0 订阅

  这题写的真是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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值