Book 书架 Zjoi2006

模板题一枚


 
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>   
#include <map>
#include <string>  
#include <climits> 
#include <set>
#include <string>    
#include <sstream>
#include <utility>   
#include <ctime>
  
using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;
using std::deque;
  
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PAIR;
typedef multimap<int, int> MMAP;
  
const int MAXN(80010);
const int MAXM(10010);
const int MAXE(10010);
const int SIGMA_SIZE(26);
const int MAXH(19);
const int INFI(2000000000);
const int MOD(1000000007);
const ULL BASE(31);
const LL LIM(10000000);
const int INV(-10000);
  
struct NODE
{
    int num, size;    //s1表示区域正数的个数
    NODE *fa, *ch[2];
};
  
NODE *point[MAXN];
int arr[MAXN];
  
struct SPLAY_TREE
{
    NODE pool[MAXN];
    NODE *root, *NIL, *rear;
    inline void push_up(NODE *sour)  
    {
        sour->size = sour->ch[0]->size+sour->ch[1]->size+1;
    }
    void initNIL()
    {
        NIL->ch[0] = NIL->ch[1] = NIL->fa = NIL;
        NIL->num = NIL->size = 0;
    }
  
    void build(NODE *&sour, NODE *tf, int l, int r)
    {
        if(l > r)
            return;
        int m = (l+r) >> 1;
        newnode(sour, tf, arr[m]);
        point[arr[m]] = sour;
        build(sour->ch[0], sour, l, m-1);
        build(sour->ch[1], sour, m+1, r);
        push_up(sour);
    }
  
    void init(int n)
    {
        NIL = pool;
        initNIL();
        rear = pool+1;
        newnode(root, NIL, 0);  //插入无穷小
        newnode(root->ch[1], root, 0); //插入无穷大
        build(root->ch[1]->ch[0], root->ch[1], 1, n); //建树
        push_up(root->ch[1]);
        push_up(root);
    }
  
    void newnode(NODE *&sour, NODE *f, int num)
    {
        sour = rear++;
        sour->num = num;
        sour->size = 1;
        sour->fa = f;
        sour->ch[0] = sour->ch[1] = NIL;
    }
  
    void rotate(NODE *sour, int flag)
    {
        NODE *f = sour->fa;
//      push_down(f);
//      push_down(sour);
        f->ch[!flag] = sour->ch[flag];
        sour->ch[flag]->fa = f;
        sour->fa = f->fa;
        if(f->fa != NIL)
            f->fa->ch[f->fa->ch[1] == f] = sour;
        sour->ch[flag] = f;
        f->fa = sour;
        push_up(f);
    }
      
    void splay(NODE *sour, NODE *goal)
    {
//      push_down(sour);
        while(sour->fa != goal)
        {
            if(sour->fa->fa == goal)
                rotate(sour, sour->fa->ch[0] == sour);
            else
            {
                NODE *f = sour->fa;
                int flag = (f->fa->ch[0] == f);
                if(f->ch[flag] == sour)
                    rotate(sour, !flag);
                else
                    rotate(f, flag);
                rotate(sour, flag);
            }
        }
        push_up(sour);
        if(goal == NIL)
            root = sour;
    }
  
    NODE *select(NODE *sour, int r)
    {
        while(sour != NIL)
        {
//          push_down(sour);
            if(r == sour->ch[0]->size+1)
                break;
            if(r <= sour->ch[0]->size)
                sour = sour->ch[0];
            else
            {
                r -= sour->ch[0]->size+1;
                sour = sour->ch[1];
            }
        }
        return sour;
    }
  
    void divide(NODE *sour)
    {
        NODE *tp1, *tp2;
        splay(sour, NIL);
        tp1 = select(root->ch[0], root->ch[0]->size);
        tp2 = select(root->ch[1], 1);
        splay(tp1, NIL);
        splay(tp2, root);
        tp2->ch[0] = NIL;
        push_up(root->ch[1]);
        push_up(root);
    }
  
    void TOP(int op)
    {
        divide(point[op]);
        NODE *tp;
        tp = select(root, 1);
        splay(tp, NIL);
        tp = select(root, 2);
        splay(tp, root);
        tp->ch[0] = point[op];
        point[op]->fa = tp;
        push_up(root->ch[1]);
        push_up(root);
    }
  
    void BOTTOM(int op)
    {
        divide(point[op]);
        NODE *tp;
        tp = select(root, root->size-1);
        splay(tp, NIL);
        tp = select(root, root->size);
        splay(tp, root);
        tp->ch[0] = point[op];
        point[op]->fa = tp;
        push_up(root->ch[1]);
        push_up(root);
    }
      
    void INSERT(int op, int T)
    {
        splay(point[op], NIL);
        int temp = root->ch[0]->size;
        divide(point[op]);
        NODE *tp = select(root, temp+T);
        splay(tp, NIL);
        tp = select(root, temp+1+T);
        splay(tp, root);
        tp->ch[0] = point[op];
        point[op]->fa = tp;
        push_up(root->ch[1]);
        push_up(root);
    }
  
    int ASK(int op)
    {
        splay(point[op], NIL);
        return root->ch[0]->size-1;
    }
  
    int QUERY(int op)
    {
        NODE *tp = select(root, op+1);
        splay(tp, NIL);
        return root->num;
    }
};
  
SPLAY_TREE spt;
  
char str[15];
int op1, op2;
  
int main()
{
    int n, m;
    while(~scanf("%d%d", &n, &m))
    {
        for(int i = 1; i <= n; ++i)
            scanf("%d", arr+i);
        spt.init(n);
        for(int i = 0; i < m; ++i)
        {
            scanf("%s%d", str, &op1);
            if(str[0] == 'T')
                spt.TOP(op1);
            else if(str[0] == 'B')
                spt.BOTTOM(op1);
            else if(str[0] == 'I')
                scanf("%d", &op2), spt.INSERT(op1, op2);
            else if(str[0] == 'A')
                printf("%d\n", spt.ASK(op1));
            else
                printf("%d\n", spt.QUERY(op1));
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值