MnZn求助 FHQ-Treap 60pts WA#6-#10
查看原帖
MnZn求助 FHQ-Treap 60pts WA#6-#10
239458
cmach_socket楼主2022/11/4 15:06

记录

初步判断应该是操作三写炸了

#include<stdio.h>
#include<time.h>
#include <stdlib.h>
#define MAXN 114514
using namespace std;
const int P=2147483647;
class node{
public:
	int w,siz,id,l,r;
}t[MAXN];
int tot,root,op,tx,n,seed=233;
int Rand(){
    return seed=(int)(seed*482711LL%P);
}
int build(int v){
    t[++tot].w=v;
    t[tot].siz=1;
    t[tot].l=t[tot].r=0;
    t[tot].id=Rand();
    return tot;
}

void update(int k){
	t[k].siz=t[t[k].l].siz+t[t[k].r].siz+1;
}
void ssplit(int k,int &x,int &y,int s)
{
    if(!k)//空节点
    {
        x=y=0;
        return;
    }
    if(s>t[t[k].l].siz)//减去左子树大小+1后进入右儿子,因为也要丢掉这个节点
        x=k,ssplit(t[k].r,t[k].r,y,s-t[t[k].l].siz-1);
    else y=k,ssplit(t[k].l,x,t[k].l,s);//进入左儿子
    update(k);//更新节点信息
}
int merge(int x,int y)
{
    if(!x || !y) return x^y;//有节点为空
    if(t[x].id<t[y].id)
    {
        t[x].r=merge(t[x].r,y);//把第一个节点的右儿子与第二个节点合并
        update(x);//更新节点信息
        return x;//返回新的根
    }
    else{
        t[y].l=merge(x,t[y].l);//把第一个节点和第二个节点的左儿子合并
        update(y);//更新节点信息
        return y;//返回新的根
    }
}
int rank(int k,int v){

    if(!k)return 0;
    if(v<t[k].w){
        return rank(t[k].l,v);
    }
    else return t[t[k].l].siz+rank(t[k].r,v)+1;
}
void insert(int v){
    int r=rank(root,v);
    int r1=0,r2=0,r3=build(v);
    ssplit(root,r1,r2,r);
    root=merge(merge(r1,r3),r2);
}
void del(int v){
    int r=rank(root,v);
    int r1=0,r2=0,r3=0;
    ssplit(root,r1,r2,r);
    ssplit(r1,r1,r3,r-1);
    r3=merge(t[r3].l,t[r3].r);
    root=merge(merge(r1,r3),r2);
}
int kth(int k){
    int r1=0,r2=0,r3=0;
    ssplit(root,r1,r2,k);
    ssplit(r1,r1,r3,k-1);
    int ans=t[r3].w;
    root=merge(merge(r1,r3),r2);
    return ans;
}
int main(){
    srand(time(NULL));
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
      scanf("%d%d",&op,&tx);  
      if(op==1){
        insert(tx);
      }
      else if(op==2){
        del(tx);
      }
      else if(op==3){
        printf("%d\n",rank(root,tx));
      }
      else if(op==4){
        printf("%d\n",kth(tx));
      }
      else if(op==5){//前に駆ける
        printf("%d\n",kth(rank(root,tx-1)));
      }
      else if(op==6){
        printf("%d\n",kth(rank(root,tx)+1));
      }

    }
	return 0;
}
2022/11/4 15:06
加载中...