非旋Treap練習題(維護父指針)ZJOI2006書架

這道題沒什麼好說的,
比較特殊的一點就是要維護父指針來查詢比指定點小的節點個數
具體看一下代碼就清楚了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 80010
using namespace std;
inline void read(int &x)
{
  int s=0,w=1;
  char c=getchar();
  while(c<'0'||c>'9')
  {
    if(c=='-')w=-1;
    c=getchar();
  }
  while(c<='9'&&c>='0')
  {
    s=(s<<3)+(s<<1)+c-'0';
    c=getchar();
  }
  x=s*w;
}
inline void write(int x)
{
  if(x<0)x=-x,putchar('-');
  if(x>9)write(x/10);
  putchar(x%10+'0');
}
template<class a,class b>class Pair
{
public:
  a first;
  b second;
  Pair(){}
  Pair(a x,b y){first=x,second=y;}
};
int seed=2333;
inline int Random(){return seed=seed*seed+seed+1;}
struct node
{
  int val,key,size;
  node *son[2],*fa;
  node(int k);
  inline void push_up();
}*nil=new node(0),*Root;
node::node(int k){val=k,key=Random(),size=1,son[0]=son[1]=fa=nil;}
inline void node::push_up()
{
  size=son[0]->size+son[1]->size+1;
  son[0]->fa=this;
  son[1]->fa=this;
}
node* merge(node *a,node *b)
{
  if(a==nil)return b;
  if(b==nil)return a;
  if(a->key<b->key)
  {
    a->son[1]=merge(a->son[1],b);
    a->push_up();
    return a;
  }
  else
  {
    b->son[0]=merge(a,b->son[0]);
    b->push_up();
    return b;
  }
}
Pair<node*,node*>split(node *root,int k)
{
  if(root==nil)return Pair<node*,node*>(nil,nil);
  Pair<node*,node*>p;
  if(root->son[0]->size>=k)
  {
    p=split(root->son[0],k);
    root->son[0]=p.second;
    root->push_up();
    p.second=root;
    return p;
  }
  else
  {
    p=split(root->son[1],k-root->son[0]->size-1);
    root->son[1]=p.first;
    root->push_up();
    p.first=root;
    return p;
  }
}
int get_size(node *root)
{
  int ans=root->son[0]->size+1;
  while(root->fa!=nil)
  {
    if(root==root->fa->son[1])ans+=root->fa->son[0]->size+1;
    root=root->fa;
  }
  return ans;
}
int n,m,a[MAXN],S,T;
node *pos[MAXN];
char opt[10];
int main()
{
  nil->size=0,Root=nil;
  Root->fa=nil;
  read(n),read(m);
  for(int i=1;i<=n;i++)
  {
    read(a[i]);
    pos[a[i]]=new node(a[i]);
    Root=merge(Root,pos[a[i]]);
  }
  while(m--)
  {
    scanf("%s",opt);
    read(S);
    if(opt[0]=='T')
    {
      Pair<node*,node*>a=split(Root,get_size(pos[S])-1),b=split(a.second,1);
      Root=merge(b.first,merge(a.first,b.second));
    }
    else if(opt[0]=='B')
    {
      Pair<node*,node*>a=split(Root,get_size(pos[S])-1),b=split(a.second,1);
      Root=merge(merge(a.first,b.second),b.first);
    }
    else if(opt[0]=='I')
    {
      read(T);
      if(T)
      {
        int size=get_size(pos[S]);
        Pair<node*,node*>a=split(Root,size-1),b=split(a.second,1);
        if(T==1)
        {
          Pair<node*,node*>c=split(b.second,1);
          Root=merge(merge(merge(a.first,c.first),b.first),c.second);
        }
        else
        {
          Pair<node*,node*>c=split(a.first,size-2);
          Root=merge(merge(merge(c.first,b.first),c.second),b.second);
        }
      }
    }
    else if(opt[0]=='A')
    write(get_size(pos[S])-1),putchar(10);
    else
    {
      Pair<node*,node*>a=split(Root,S-1),b=split(a.second,1);
      write(b.first->val),putchar(10);
      Root=merge(a.first,merge(b.first,b.second));
    }
}

luogu評測720ms
表現還可以,沒有比Splay慢太多

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值