[ZJOI2006]书架

题目

洛谷

思路

首先,我们可以用一个map存一下每一个key值对应的点的编号和每一个点对应的key;用两个变量记录出现过的最大的key和最小的key。

  1. Q操作,就是普通的查询,得到key值后输出对应的点编号即可
  2. T操作,将原本的点删去,然后插入一个key为(Minkey - 1)的点,即把此点放到第一个。更新即可。
  3. B操作,和T操作类似,插入key为(Maxkey + 1)的点。
  4. A操作,也是普通的查询,输入s点对应key值的排名-1即可
  5. I操作,因为只会与前一位或后一位的点交换,将这两个点得key值交换即可。

Code:

#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAXN 160005
#define LL long long
#define Mod 1000000
#define Int_Max 2147483647
#define INF 0x3f3f3f3f
#define Int register int
using namespace std;
struct node
{
    int Size, Key, l, r, Rank, Xiu;
}Point[MAXN];
int Num;
map<int, int> Pointof;
int Max(int x,int y)
{
    return x > y ? x : y;
}
int Abs(int x)
{
    if (x > 0)
     	return x;
    return -x;
}
int Min(int x,int y)
{
    return x < y ? x : y;
}
inline void read(int &x)
{
    x = 0;
    int f = 1;
    char s = getchar();
    while (s < '0' || s > '9')
    {
     	if (s == '-')
      	    f = -1;
     	s = getchar();
    }
    while (s >= '0' && s <= '9')
    {
     	x = (x << 3) + (x << 1) + (s ^ 48);
     	s = getchar();
    }
    x *= f;
}
int GetHash()
{
    static int Seed = 122520;
    Seed = (int)Seed * 520122ll % Int_Max;
    return Seed;
}
void Update(int x)
{
    Point[x].Size = Point[Point[x].l].Size + Point[Point[x].r].Size + Point[x].Rank;
}
void Lturn(int &x)
{
    int rson = Point[x].r;
    Point[x].r = Point[rson].l;
    Point[rson].l = x;
    Point[rson].Size = Point[x].Size;
    Update( x );
    x = rson;
}
void Rturn(int &x)
{
    int lson = Point[x].l;
    Point[x].l = Point[lson].r;
    Point[lson].r = x;
    Point[lson].Size = Point[x].Size;
    Update( x );
    x = lson;
}
void Insert(int &x,int val)
{
    if (! x)
    {
        x = ++ Num;
     	Point[x].Size = Point[x].Rank = 1;
     	Point[x].Key = val;
     	Point[x].Xiu = rand();
     	return ;
    }
    Point[x].Size ++;
    if (Point[x].Key == val)
     	Point[x].Rank ++;
    else if (val > Point[x].Key)
    {
     	Insert(Point[x].r, val);
     	if (Point[Point[x].r].Xiu < Point[x].Xiu)
      	    Lturn( x );
    }
    else
    {
     	Insert(Point[x].l, val);
     	if (Point[Point[x].l].Xiu < Point[x].Xiu)
      	    Rturn( x );
    }
}
void Delete(int &x,int val)
{
    if (! x)
     	return ;
    if (Point[x].Key == val)
    {
     	if (Point[x].Rank > 1)
      	    Point[x].Rank --, Point[x].Size --;
     	else
     	{
      	    if (! Point[x].l || ! Point[x].r)
    x = Point[x].l + Point[x].r;
       	    else if (Point[Point[x].l].Xiu < Point[Point[x].r].Xiu)
       	        Rturn( x ), Delete(x, val);
       	    else Lturn( x ), Delete(x, val);
        }
    }
    else if (val > Point[x].Key)
      Point[x].Size --, Delete(Point[x].r, val);
    else Point[x].Size --, Delete(Point[x].l, val);
}
int GetRank(int x,int val)
{
    if (! x)
     	return 0;
    if (Point[x].Key == val)
     	return Point[Point[x].l].Size + 1;
    if (val > Point[x].Key)
     	return Point[Point[x].l].Size + Point[x].Rank + GetRank(Point[x].r, val);
    else return GetRank(Point[x].l, val);
}
int GetXth(int x,int val)
{
    if (! x)
     	return 0;
    if (val <= Point[Point[x].l].Size)
     	return GetXth(Point[x].l, val);
    val -= Point[Point[x].l].Size;
    if (val <= Point[x].Rank)
     	return Point[x].Key;
    val -= Point[x].Rank;
    return GetXth(Point[x].r, val);
}
int FindHead(int x,int val)
{
    if (! x)
     	return -INF;
    if (Point[x].Key > val)
     	return FindHead(Point[x].l, val);
    else return Max(Point[x].Key, FindHead(Point[x].r, val));
}
int FindBack(int x,int val)
{
    if (! x)
     	return INF;
    if (Point[x].Key <= val)
     	return FindBack(Point[x].r, val);
    else return Min(Point[x].Key, FindBack(Point[x].l, val));
}
inline void Swap(int &x,int &y)
{
    int temp = x;
    x = y;
    y = temp;
}
int Order[MAXN];
int Root, Maxkey, Minkey;
int main()
{
    srand(*new unsigned);
    int n, m;
    read( n ); read( m );
    Maxkey = n, Minkey = 1;
    for (Int i = 1; i <= n; ++ i)
    {
     	int Bh;
     	read( Bh );
     	Insert(Root, i);
     	Order[Bh] = i;
     	Pointof[i] = Bh;
    }
    for (Int i = 1; i <= m; ++ i)
    {
     	char Or[10];
     	scanf("%s", Or);
     	switch( Or[0] )
     	{
      	    case 'Q':
     	    {
       		int k;
       		read( k );
       		int Get = GetXth(Root, k);
       		printf("%d\n", Pointof[Get]);
        	break;
            }
     	    case 'T':
   	    {
       		int k;
       		read( k );
        	Delete(Root, Order[k]);
        	Insert(Root, -- Minkey);
        	Order[k] = Minkey;
        	Pointof[Minkey] = k;
        	break;
      	    }
       	    case 'B':
       	    {
        	int k;
        	read( k );
        	Delete(Root, Order[k]);
        	Insert(Root, ++ Maxkey);
        	Order[k] = Maxkey;
        	Pointof[Maxkey] = k;
        	break;
       	    }
       	    case 'A':
       	    {
        	int k;
        	read( k );
        	int Get = GetRank(Root, Order[k]);
        	printf("%d\n", Get - 1);
        	break;
   	    }
       	    case 'I':
   	    {
        	int k, t;
        	read( k ); read( t );
        	int Want = GetRank(Root, Order[k]);
        	int KK = GetXth(Root, Want + t);
        	int PP = Pointof[KK];
        	Swap(Pointof[Order[k]], Pointof[KK]);
        	Swap(Order[k], Order[PP]);
        	break;
       	    }
      	}
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值