• [ZJOI2006]书架


    fhq treap

    开个minnmaxn作排序标准

    置顶就更新val=--minn,垫底就更新val=++maxn

    改变位置就相当于找前驱后继swap(val1,val2)

    找排名为k的编号就是二叉查找树的模板

    找编号为k前面的书个数就拆树取左边的siz

    #include"cstdio"
    #include"cstring"
    #include"iostream"
    #include"algorithm"
    #include"ctime"
    using namespace std;
    
    const int MAXN=8e4+5;
    
    int n,m,cnt,minn,root,maxn;
    int siz[MAXN],sn[MAXN][2];
    int rev[MAXN],val[MAXN];
    char ch[16];
    
    int cret(int x,int v)
    {
    	siz[x]=1;
    	val[x]=v;
    	rev[x]=rand();
    	sn[x][0]=sn[x][1]=0;
    	return x;
    }
    
    int un(int x,int y)
    {
    	if(!x||!y) return x|y;
    	if(rev[x]<rev[y]){
    		sn[x][1]=un(sn[x][1],y);
    		siz[x]=siz[sn[x][0]]+siz[sn[x][1]]+1;
    		return x;
    	}sn[y][0]=un(x,sn[y][0]);
    	siz[y]=siz[sn[y][0]]+siz[sn[y][1]]+1;
    	return y;
    }
    
    void dro(int k,int v,int &x,int &y)
    {
    	if(!k){x=y=0;return;}
    	if(val[k]<=v) x=k,dro(sn[k][1],v,sn[k][1],y);
    	else y=k,dro(sn[k][0],v,x,sn[k][0]);
    	siz[k]=siz[sn[k][0]]+siz[sn[k][1]]+1;
    	return;
    }
    
    int rnk(int k,int v)
    {
    	if(v<=siz[sn[k][0]]) return rnk(sn[k][0],v);
    	if(v==siz[sn[k][0]]+1) return k;
    	return rnk(sn[k][1],v-siz[sn[k][0]]-1);
    }
    
    void debug()
    {
    	for(int i=1;i<=n;++i) printf("%d ",rnk(root,i));
    	puts("");
    }
    
    void Tp()
    {
    	int v,x,y,z;scanf("%d",&v);
    	dro(root,val[v],x,z),dro(x,val[v]-1,x,y);
    	y=un(sn[y][0],sn[y][1]);root=un(un(x,y),z);
    	--minn;cret(v,minn);
    	dro(root,val[v],x,y);
    	root=un(un(x,v),y);
    	return;
    }
    
    void Bt()
    {
    	int v,x,y,z;scanf("%d",&v);
    	dro(root,val[v],x,z),dro(x,val[v]-1,x,y);
    	y=un(sn[y][0],sn[y][1]);root=un(un(x,y),z);
    	++maxn;cret(v,maxn);
    	dro(root,val[v],x,y);
    	root=un(un(x,v),y);
    	return;
    }
    
    void del(int v)
    {
    	int x,y,z;
    	dro(root,val[v],x,z);dro(x,val[v]-1,x,y);
    	y=un(sn[y][0],sn[y][1]);
    	root=un(un(x,y),z);
    	return;
    }
    
    void Ins()
    {
    	int v,u,x,y,tmp;scanf("%d%d",&v,&u);
    	if(!u) return;
    	if(u==1) dro(root,val[v],x,y),tmp=rnk(y,1),root=un(x,y);
    	else dro(root,val[v]-1,x,y),tmp=rnk(x,siz[x]),root=un(x,y);
    	int v1=val[v],v2=val[tmp];
    	del(v);del(tmp);
    	dro(root,v1,x,y);root=un(un(x,cret(tmp,v1)),y);
    	dro(root,v2,x,y);root=un(un(x,cret(v,v2)),y);
    	return;
    }
    
    void As()
    {
    	int v,x,y;scanf("%d",&v);
    	dro(root,val[v]-1,x,y);
    	printf("%d
    ",siz[x]);
    	root=un(x,y);
    	return;
    }
    
    void Cas()
    {
    	int v,x,y;scanf("%d",&v);
    	printf("%d
    ",rnk(root,v));
    	return;
    }
    
    int main()
    {
    	scanf("%d%d",&n,&m);maxn=n;
    	for(int i=1;i<=n;++i){
    		int v,x,y;scanf("%d",&v);
    		dro(root,i,x,y);
    		root=un(un(x,cret(v,i)),y);
    	}while(m--){
    		scanf("%s",ch+1);
    		if(ch[1]=='T') Tp();
    		else if(ch[1]=='B') Bt();
    		else if(ch[1]=='I') Ins();
    		else if(ch[1]=='A') As();
    		else Cas();
    	}return 0;
    }
    
  • 相关阅读:
    Java WebService异构系统通信的原理及特点:SOAP与WSDL
    jenkins下拉框选择构建环境
    vue中的hash与history
    一行代码轻松搞定企微内嵌h5调用原生api不生效问题
    开源绘图工具plantUML入门教程(常用于画时序图等)
    什么是持续集成、持续交付、持续部署(CI/CD)?
    一篇文章了解CI/CD管道全流程
    开源免费的SSH工具推荐:electerm(推荐)、Finalshell
    Oracle数据库设置表空间自动扩展(解决因表空间不足引起的ORA01653: unable to extend table错误)
    测试工作中浏览器F12工具简单使用介绍
  • 原文地址:https://www.cnblogs.com/AH2002/p/10072225.html
Copyright © 2020-2023  润新知