P3835 【模板】可持久化平衡树

题面

https://www.luogu.org/problem/P3835

题解

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<ctime>

using namespace std;
struct fhq_treap {
  int v[500050*50],fix[500050*50],ch[500050*50][2],siz[500050*50];
  int root[500050],cnt;
  void clear() {cnt=0;}
  void copy(int x,int y) {
    v[y]=v[x]; fix[y]=fix[x]; ch[y][0]=ch[x][0]; ch[y][1]=ch[x][1]; siz[y]=siz[x];
  }
  void update(int x) { siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1; }
  void split(int k,int x,int y,int &ch1,int &ch2) {
    if (!x) {
      ch2=ch1=0;
      return;
    }
    copy(x,y);
    if (v[y]<=k) {
      ch1=y;
      split(k,ch[y][1],++cnt,ch[y][1],ch2);
    }
    else {
      ch2=y;
      split(k,ch[y][0],++cnt,ch1,ch[y][0]);
    }
    update(y);
  }
  int merge(int x,int y) {
    if (!x || !y) return x+y;
    if (fix[x]<fix[y]) {
      ch[x][1]=merge(ch[x][1],y);
      update(x);
      return x;
    }
    else {
      ch[y][0]=merge(x,ch[y][0]);
      update(y);
      return y;
    }
  }
  int newnode(int val) {
    ++cnt;
    v[cnt]=val; fix[cnt]=rand(); siz[cnt]=1;
    return cnt;
  }
  void insert(int his,int cur,int val) {
    int root1=0,root2=0;
    split(val,root[his],++cnt,root1,root2);
    root[cur]=merge(merge(root1,newnode(val)),root2);
  }
  void erase(int his,int cur,int val) {
    int root1=0,root2=0,root3=0;
    split(val,root[his],++cnt,root1,root3);
    split(val-1,root1,++cnt,root1,root2);
    root2=merge(ch[root2][0],ch[root2][1]);
    root[cur]=merge(merge(root1,root2),root3);
  }
  int findkth(int k,int his,int cur) {
    int now=root[cur]=root[his];
    int rk=1;
    while (now) {
      if (siz[ch[now][0]]+rk==k) return v[now];
      else if (siz[ch[now][0]]+rk>k) now=ch[now][0]; else rk+=siz[ch[now][0]]+1,now=ch[now][1];
    }
    return -1;
  }
  int findrank(int k,int his,int cur) {
    int root1=0,root2=0;
    split(k-1,root[his],++cnt,root1,root2);
    int ret=siz[root1]+1;
    root[cur]=merge(root1,root2);
    return ret;
  }
  int findpre(int k,int his,int cur) {
    int pre=-2147483647;
    int now=root[cur]=root[his];
    while (now) {
      if (v[now]<k) pre=max(pre,v[now]),now=ch[now][1]; else now=ch[now][0];
    }
    return pre;
  }
  int findsuc(int k,int his,int cur) {
    int suc=2147483647;
    int now=root[cur]=root[his];
    while (now) {
      if (v[now]>k) suc=min(suc,v[now]),now=ch[now][0]; else now=ch[now][1];
    }
    return suc;
  }
} treap;

int n;
int main() {
  int i,his,opt,x;
  srand(time(0));
  treap.clear();
  scanf("%d",&n);
  for (i=1;i<=n;i++) {
    scanf("%d %d %d",&his,&opt,&x);
    if (opt==1) treap.insert(his,i,x);
    if (opt==2) treap.erase(his,i,x);
    if (opt==3) printf("%d\n",treap.findrank(x,his,i));
    if (opt==4) printf("%d\n",treap.findkth(x,his,i));
    if (opt==5) printf("%d\n",treap.findpre(x,his,i));
    if (opt==6) printf("%d\n",treap.findsuc(x,his,i));
  }
  return 0;
}

 

转载于:https://www.cnblogs.com/shxnb666/p/11427320.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值